0Pricing
React Native Academy · 강의

useEffect 훅과 의존성 배열

useEffect가 실행되는 시점을 이해하고 의존성 배열로 실행을 제어하며, 정리 함수를 반환해 구독 또는 타이머를 정리합니다.

useEffect 훅과 의존성 배열은(는) CoddyKit의 무료 React Native Academy 강의입니다. 이것은 4개 중 1번째 강의입니다. 아래에서 전체 강의를 무료로 읽을 수 있으며, 내장 코드 에디터와 24/7 AI 튜터와 함께 브라우저에서 직접 실습할 수 있습니다. 이 강의는 React Native Academy 학습 경로의 일부이며, 진행 상황이 웹과 CoddyKit 앱에 동기화됩니다. React Native Academy 강의에는 총 4개의 강의가 포함되어 있습니다.

이 강의의 일부는 아직 번역되지 않았으며 영어로 표시됩니다.

What is useEffect?

useEffect lets function components perform side effects: fetching data, setting up subscriptions, manipulating the DOM, starting timers, or calling native APIs. Side effects cannot be run directly in the render function because renders must be pure. useEffect runs after the component renders to the screen.

import { useEffect } from 'react';

function App() {
  useEffect(() => {
    console.log('Component rendered');
    // Side effects go here
  });
}

The Dependency Array

The second argument to useEffect is the dependency array. React uses it to decide when to re-run the effect. If the dependency array is omitted, the effect runs after every render. If it is empty ([]), the effect runs once after the initial render. If it contains values, the effect re-runs whenever any of those values change.

// Runs after every render
useEffect(() => { ... });

// Runs once on mount
useEffect(() => { ... }, []);

// Runs on mount and whenever userId changes
useEffect(() => { ... }, [userId]);

Fetching Data on Mount

The most common useEffect pattern is fetching data when a component first mounts. Pass an empty dependency array to ensure the fetch runs exactly once. Store the result in state and render it in the JSX. React calls the effect after the initial paint, so the component renders once with empty/loading state before the data arrives.

function PostsScreen() {
  const [posts, setPosts] = useState([]);

  useEffect(() => {
    fetch('https://jsonplaceholder.typicode.com/posts')
      .then((res) => res.json())
      .then((data) => setPosts(data));
  }, []); // empty array = run once on mount

  return <FlatList data={posts} ... />;
}

Reactive Dependencies

When you want the effect to re-run whenever a value changes (like a search query or a user ID), list that value in the dependency array. React compares each dependency with its previous value after every render, and if any have changed, it re-runs the effect. This creates a reactive data flow: UI event → state update → effect re-runs.

function UserProfile({ userId }) {
  const [user, setUser] = useState(null);

  useEffect(() => {
    fetch('/api/users/' + userId)
      .then((res) => res.json())
      .then((data) => setUser(data));
  }, [userId]); // re-fetch whenever userId changes

  if (!user) return <ActivityIndicator />;
  return <Text>{user.name}</Text>;
}

The Cleanup Function

Return a function from your effect to perform cleanup. React calls this cleanup function before re-running the effect (on dependency changes) and when the component unmounts. Use it to cancel subscriptions, clear timers, or abort fetch requests to prevent memory leaks and state updates on unmounted components.

useEffect(() => {
  const timer = setInterval(() => {
    setTime(Date.now());
  }, 1000);

  return () => clearInterval(timer); // cleanup on unmount or re-run
}, []);

Cancelling Fetch Requests with AbortController

When a component unmounts before a fetch completes, React will warn about updating state on an unmounted component. Use the AbortController to cancel the in-flight fetch in the cleanup function. Catching the abort error (which is an AbortError) prevents it from being logged as an unexpected error.

useEffect(() => {
  const controller = new AbortController();

  fetch('/api/data', { signal: controller.signal })
    .then((res) => res.json())
    .then((data) => setData(data))
    .catch((err) => {
      if (err.name !== 'AbortError') setError(err);
    });

  return () => controller.abort();
}, []);

Running Code Only on Unmount

To run code only when the component unmounts (like unsubscribing from an event listener), return a cleanup function from a useEffect with an empty dependency array. React calls the cleanup only when the component leaves the tree, never on subsequent renders.

useEffect(() => {
  const subscription = eventEmitter.addListener('change', handler);

  return () => {
    subscription.remove(); // only on unmount
  };
}, []); // empty array = mount-only effect

Multiple useEffect Calls

You can and should use multiple useEffect calls in one component — one for each independent side effect. React runs them in the order they appear after every render. Keeping effects separated by concern makes the code easier to read and avoids complex dependency arrays that mix unrelated logic.

// Effect 1: fetch user data
useEffect(() => {
  fetchUser(userId).then(setUser);
}, [userId]);

// Effect 2: analytics page view
useEffect(() => {
  analytics.logScreenView('Profile');
}, []);

// Effect 3: sync title to header
useEffect(() => {
  navigation.setOptions({ title: user?.name ?? 'Profile' });
}, [user, navigation]);

Dependency Pitfalls: Missing Dependencies

A common bug is omitting a dependency from the array. The effect captures a stale value of the missing dependency and runs with outdated data. Always include every value from the component scope that is read inside the effect. ESLint's react-hooks/exhaustive-deps rule catches these automatically.

// Bug: fetchUser uses userId but it is not in deps
// If userId changes, the effect still runs with the old userId
useEffect(() => {
  fetchUser(userId).then(setUser);
}, []); // Missing userId!

// Correct:
useEffect(() => {
  fetchUser(userId).then(setUser);
}, [userId]);

Avoiding Infinite Loops

If your effect updates state that is also listed as a dependency, you get an infinite loop: render → effect → state update → render → effect → .... Guard against this with a condition inside the effect, or restructure so the effect does not trigger the state update that caused it to run.

// Infinite loop: effect updates 'count' which is in deps
useEffect(() => {
  setCount(count + 1); // triggers re-render → effect runs again
}, [count]);

// Fix: use functional updater — no need to list count as dep
useEffect(() => {
  setCount((c) => c + 1);
}, []); // only runs once

Comparing Effects to Lifecycle Methods

useEffect replaces all three classic class component lifecycle methods: componentDidMount (empty deps array), componentDidUpdate (with deps), and componentWillUnmount (cleanup function). One hook handles all three phases, keeping related logic together rather than spread across three separate methods.

useEffect(() => {
  // componentDidMount equivalent — fetch initial data
  fetchData();

  return () => {
    // componentWillUnmount equivalent — cancel subscriptions
    cancelSubscription();
  };
}, []); // runs once on mount, cleanup on unmount

Quick Check

Test your understanding of the useEffect hook and dependency arrays from this lesson.

Lesson Recap

In this lesson you learned: useEffect runs side effects after render, the dependency array controls when the effect re-runs — empty means once on mount, and return a cleanup function to cancel subscriptions, timers, and fetch requests on unmount. Next up we make GET requests with Axios inside useEffect.

자주 묻는 질문

“useEffect 훅과 의존성 배열” 강의는 무료인가요?

네 — “useEffect 훅과 의존성 배열” 전체 내용을 이 웹사이트에서 무료로 읽을 수 있습니다. 인터랙티브하게 실습하려면(내장 코드 에디터와 24/7 AI 튜터), CoddyKit PRO로 업그레이드하면 React Native Academy 강의 전체를 잠금 해제할 수 있습니다. React Native Academy 강의에는 총 4개의 강의가 포함되어 있습니다.

“useEffect 훅과 의존성 배열”에서 뭘 배우나요?

useEffect가 실행되는 시점을 이해하고 의존성 배열로 실행을 제어하며, 정리 함수를 반환해 구독 또는 타이머를 정리합니다. 브라우저에서 직접 실행하는 실습 코드로 React Native Academy을(를) 배우며, 24/7 AI 튜터가 강의를 진행하면서 질문에 답변해줍니다.

React Native Academy을(를) 시작하는 데 경험이 필요한가요?

사전 경험은 필요하지 않습니다. CoddyKit의 React Native Academy은(는) 초급자부터 고급 학습자까지를 위해 구성되어 있으므로, 여기서 시작하거나 처음부터 시작할 수 있으며 자신의 속도대로 진행할 수 있습니다. 이것은 4개 중 1번째 강의입니다.

“useEffect 훅과 의존성 배열” 강의는 얼마나 걸리나요?

대부분의 CoddyKit 강의는 약 5~10분이 소요됩니다. 각 강의는 간결하고 인터랙티브하여 꾸준한 진행이 가능하며, 웹과 앱에서 중단한 부분부터 바로 시작할 수 있습니다.

이 React Native Academy 강의에서 코드를 작성하고 실행할 수 있나요?

네. 모든 React Native Academy 강의에는 내장 코드 에디터가 포함되어 있으므로, 브라우저에서 바로 실제 코드를 작성하고 실행한 후 즉시 AI 피드백을 받을 수 있습니다 — 로컬 설정이 필요 없습니다.

이 강의의 모든 강의

  1. useEffect 훅과 의존성 배열
  2. Axios로 GET 요청 보내기
  3. 로딩 및 오류 상태 처리
  4. Axios로 POST, PUT 및 DELETE 사용하기
← React Native Academy(으)로 돌아가기