• 카테고리

    질문 & 답변
  • 세부 분야

    프론트엔드

  • 해결 여부

    해결됨

useEffect() 안에 함수를 정의하는 이유가 무엇인가요?

23.09.13 13:57 작성 조회수 1.18k

1

안녕하세요, 소플님.

챕터 7 나만의 훅 만들기를 공부하다가 궁금한 점이 있어서 질문드립니다.

 

228쪽 커스텀 훅 추출하기 예제 코드에서

function useUserStatus(userId) {
  //...

  useEffect(() => {
    function handleStatusChange(status) {
      //...
    }

    //...
  })

  //...
}

이런 식으로 useEffect 안에 handleStatusChange 함수를 정의하셨는데,

useUserStatus 바로 아래에 정의하지 않고 useEffect 안에 정의하신 이유가 있을까요?

어떤 상황에서 useEffect 안에 함수를 정의해야 하는 것인지 궁금합니다.

 

감사합니다.

답변 1

답변을 작성해보세요.

1

안녕하세요, 소플입니다.

handleStatusChange() 라는 함수는 useEffect() 훅 내부에서만 사용하는 함수이기 때문에,
useEffect() 훅의 내부에서 선언해서 사용한 것입니다.

책의 214p에서 useEffect() 훅을 설명할 때 나온 부분의 코드처럼,
아래와 같이 useEffect() 훅의 바깥에서 선언해서 사용할 수도 있지만,
이렇게 하게 되면 컴포넌트가 재렌더링 될 때마다 매번 함수가 새로 정의됩니다.

import { useState, useEffect } from 'react';

function useUserStatus(props) {
    const [isOnline, setIsOnline] = useState(null);

    function handleStatusChange(status) {
        setIsOnline(status.isOnline);
    }

    useEffect(() => {
        ServerAPI.subscribeUserStatus(props.user.id, handleStatusChange);
        return () => {
            ServerAPI.unsubscribeUserStatus(props.user.id, handleStatusChange);
        };
    });

    return isOnline;
}

export default useUserStatus;

그래서 불필요한 함수 재정의를 방지하고 함수의 scope를 최소화 시키기 위해서
useEffect() 훅 내부에 함수를 선언하는 것이라고 보면 됩니다.

물론 위 코드의 useEffect() 훅은 의존성 배열이 없기 때문에 매 렌더링마다 Effect 함수가 실행됩니다.
(클래스 컴포넌트의 componentDidUpdate()를 생각하면 됩니다.)

 

그리고 추가로 useEffect() 훅 내부에 함수를 정의하는 경우는 비동기 호출을 하는 경우가 있습니다.

예를 들어, 컴포넌트가 마운트 된 이후에 서버로부터 데이터를 받아오고자 하는 경우,
일반적으로 아래와 같이 시도해보게 됩니다.

import { useEffect } from 'react';

function MyComponent(props) {
    useEffect(async () => {
        const response = await ServerAPI.fetchUserData();

        // Do something with response
        // ...
    }, []);

    return <div>Hello, MyComponent!</div>;
}

export default MyComponent;

하지만 위와 같이 코드를 작성하면 아래와 같은 경고 메시지가 뜨게 됩니다.

Effect callbacks are synchronous to prevent race conditions. Put the async function inside:

이 말은 Effect 함수는 race condition을 방지하기 위해서 비동기가 아닌 동기 방식으로 실행되기 때문에,
Effect 함수에 async를 붙이면 안 된다는 것입니다.

그래서 보통은 아래 코드와 같이 useEffect() 훅 내부에 비동기 함수를 정의하고,
정의한 함수를 호출하는 형태로 사용합니다.

import { useEffect } from 'react';

function MyComponent(props) {
    useEffect(() => {
        async function fetchUserData(status) {
            const response = await ServerAPI.fetchUserData();

            // Do something with response
            // ...
        }

        fetchUserData();
    }, []);

    return <div>Hello, MyComponent!</div>;
}

export default MyComponent;

 

개발하면서 훅을 여러가지 형태로 사용해보고 console.log()를 출력해서 결과도 보시면,
더 빠르게 이해하실 수 있을 것입니다.

학습 중 추가로 더 궁금한 부분은 언제든지 질문해주시기 바랍니다!

감사합니다.

양우진님의 프로필

양우진

질문자

2023.09.14

궁금했던 점이 완전히 해결되었습니다!

자세한 설명 감사합니다..!