[2024.06.11] TIL 36일차

김선민·2024년 6월 11일

useEffect란?

  • 리액트 컴포넌트가 렌더링 될 때마다 특정 작업을 실행할 수 있도록 하는 Hook
  • useEffect는 컴포넌트가
    mount 됐을 때,
    컴포넌트가 unmount 됐을 때,
    컴포넌트가 update 됐을 때, 특정 작업을 처리할 수 있다.

useEffect의 기본 형태

[ useEffect( function, deps ) ]

  • function : 수행하고자하는 작업

  • deps : 배열 형태이며, 배열 안에는 검사하고자 하는 특정 값 or 빈 배열

  • useEffect의 기본 return 값은 undefined이다.

  • 컴포넌트의 최상위 레벨에서 useEffect를 호출하여 Effect를 선언한다.

	import { useEffect } from "react";

[ deps 여부의 차이점 ]

1. 의존성 배열을 생략한 경우

    useEffect(() => {
    	console.log('컴포넌트가 렌더링 될 때마다 실행');
    });

2. 빈 배열을 전달한 경우

	function ExampleComponent() {
      useEffect(() => {
          console.log('컴포넌트가 처음 마운트 될 때만 실행');
      }, []);
      
      return <div>안녕하세요!</div>
    }

3. 특정 값들이 포함된 배열을 전달한 경우

    function ExampleComponent() {
      const [count, setCount] = useState(0);

      useEffect(() => {
      	console.log('업데이트 될 때 실행')
        console.log(`count 값이 변경되었습니다: ${count}`);
      }, [count]);

      return (
        <div>
          <p>{count} 번 클릭했습니다</p>
          <button onClick={() => setCount(count + 1)}>클릭</button>
        </div>
      );
    }

useEffect 매개변수

  • setup 함수

    • setup은 Effect의 로직에 담긴 함수
    • 이 함수는 컴포넌트가 DOM에 추가될 때 실행되고, 선택적으로 cleanup 함수를 반환 가능
      • 컴포넌트가 DOM에 추가될 때
        React가 setup 함수를 실행
      • 의존성이 변경되어 컴포넌트가 다시 렌더링될 때
        React가 이전 값으로 cleanup 함수를 실행 후 새로운 값으로 setup 함수를 다시 실행
      • 컴포넌트가 DOM에서 제거될 때
        React가 마지막으로 cleanup 함수를 실행
  • optional dependencies 함수 (선택적 의존성)
    • deps는 setup 코드 내에서 참조되는 모든 반응형 값의 목록
    • props, state, 그리고 컴포넌트 내부에서 선언된 모든 변수와 함수가 포함
      • 목록 작성
        의존성 목록은 [dep1, dep2, dep3]과 같은 고정된 수의 항목을 가진 배열 형태로 작성
      • 변화 감지
        의존성 목록의 각 항목을 이전 값과 비교하여 변화가 있을때만 setup 함수를 실행
      • 린터 검사
        React용으로 구성된 린터는 모든 반응형 값이 의존성 배열에 바르게 지정되었는지 확인
              function ExampleComponent() {
                const [count, setCount] = useState(0);

                // useEffect 안에 전달된 함수가 바로 setup 함수입니다.
                useEffect(() => {
                  console.log(`count 값이 변경되었습니다: ${count}`);

                  // 이 함수는 cleanup 함수로, setup 함수가 실행되기 전에 실행됩니다.
                  return () => {
                    console.log('클린업 중...');
                  };
                }, [count]); // 이 부분은 의존성 배열입니다.

                return (
                  <div>
                    <p>{count} 번 클릭했습니다</p>
                    <button onClick={() => setCount(count + 1)}>클릭</button>
                  </div>
                );
              }

주의사항

  1. useEffect는 컴포넌트의 최상위 레벨이나 자체적인 훅에서만 호출할 수 있다.

    • 반복문이나 조건문 내에서는 사용할 수 없음
    • 이럴 때는 새로운 컴포넌트를 추출하고 상태를 이동시켜야 함
  2. 외부 시스템과의 동기화를 위한 목적이 아니라면, 보통 useEffect가 필요하지 않을 수 있다.

  3. Strict 모드가 켜져있을 때, 첫번째 실제 셋업 전에 개발용 셋업 및 클린업 사이클을 한번 더 실행한다.

    • 이는 클린업 로직이 셋업 로직과 일치하는지 확인,
    • 셋업이 수행한 작업을 중지하거나 취소하는지 확인하는 스트레스 테스트
  4. 컴포넌트 내부에 정의된 객체나 함수가 의존성으로 사용될 경우, 불필요하게 useEffect가 더 자주 다시 실행될 수 있다.

    • 이를 해결하기 위해 불필요한 객체나 함수 의존성을 제거하거나,
    • Effect 외부로 상태 업데이트와 반응하지 않는 로직을 추출
  5. Effect가 사용자 상호작용으로 인해 발생하지 않았다면, React는 보통 브라우저가 화면을 업데이트 한 후에 Effect를 실행한다.

    • 만약 Effect가 시각적인 작업을 수행하고 있고 지연이 눈에 띄면 useEffect 대신 useLayoutEffect로 대체해야 함
  6. 심지어 Effect가 사용자 상호작용으로 인해 발생했더라도, 브라우저는 상태 업데이트를 처리하기 전에 화면을 다시 그릴 수 있다.

    • 이것은 보통 원하는 동작이지만, 화면을 다시 그리지 않도록 브라우저를 차단해야 할 경우
      useEffect를 useLayoutEffect로 대체해야 함
  7. Effects는 클라이언트에서만 실행되며, 서버 렌더링 중에는 실행되지 않는다.

사용법

외부 시스템 연결하기

  • 때로는 컴포넌트가 페이지에 표시되는 동안 네트워크, 일부 브라우저 API 또는 타사 라이브러리에 연결 상태를 유지해야 할 수도 있다.
  • 이러한 시스템은 React에서 제어되지 않으므로 외부(external)라고 한다.
import { useEffect } from 'react';
import { createConnection } from './chat.js';

function ChatRoom({ roomId }) {
  const [serverUrl, setServerUrl] = useState('https://localhost:1234');

  useEffect(() => {
  	const connection = createConnection(serverUrl, roomId);
    connection.connect();

  	return () => {
      connection.disconnect();
  	};
  }, [serverUrl, roomId]);
  // ...
}
  1. createConnection 함수를 사용하여 서버와의 연결을 생성한다.
    • 이 함수는 서버 URL과 채팅방 ID를 인자로 받아서 해당 채팅방에 연결을 설정
    • 그리고 이 연결 객체를 connection 변수에 저장
  2. 연결 객체를 만든 후에는 connect 메서드를 호출하여 서버와의 연결을 수립한다.
  3. 여기서의 cleanup 함수인 disconnect 메서드를 호출하여 서버와의 연결을 종료한다.
    • 이 함수는 컴포넌트가 제거되거나 업데이트되기 전에 실행됨
    • 이렇게 함으로써 메모리 누수를 방지하고 불필요한 리소스를 해제할 수 있음
  4. 마지막으로 useEffect의 의존성 배열을 확인한다.
    • serverUrl과 roomId가 포함
    • 이는 useEffect가 실행될 조건을 결정하는데, 만약 이 값들이 변경되면 새로운 연결을
      설정해야 하기 때문

커스텀 훅으로 Effect 감싸기

  • Effect를 수동으로 작성해야 하는 경우가 자주 발생한다면 이는 컴포넌트가 의존하는 일반적인 동작에 대한 커스텀 훅을 추출해야 한다는 신호일 수 있다.
  • 예를 들어, 이 useChatRoom 커스텀 훅은 Effect의 로직을 보다 선언적인 API 뒤에 숨긴다.
function useChatRoom({ serverUrl, roomId }) {
  useEffect(() => {
    const options = {
      serverUrl: serverUrl,
      roomId: roomId
    };
    const connection = createConnection(options);
    connection.connect();
    return () => connection.disconnect();
  }, [roomId, serverUrl]);
}
  1. useChatRoom 훅은 서버와 채팅방의 연결을 설정하고 관리하는 역할을 한다.
    • useChatRoom은 serverUrl과 roomId라는 두 개의 매개변수를 받음
    • serverUrl : 연결할 서버의 URL
    • roomId : 채팅방의 ID
  2. useEffect 훅은 의존성 배열에 있는 값이 변경될 때마다 실행
    • 컴포넌트가 처음 마운트될 때와 serverUrl 또는 roomId가 변경될 때마다 실행
  3. const option 부분은 연결을 설정한다.
    • createConnection 함수를 호출하여 서버와의 연결 객체를 생성
    • connection.connect()를 호출하여 연결을 수립
  4. useEffect는 cleanup 함수를 반환한다.
    • 이 함수는 컴포넌트가 언마운트되거나 의존성 배열의 값이 변경될 때 호출되어 연결을 해제합니다.
  function ChatRoom({ roomId }) {
    const [serverUrl, setServerUrl] = useState('https://localhost:1234');

    useChatRoom({
      roomId: roomId,
      serverUrl: serverUrl
    });
    // ...
  1. ChatRoom 컴포넌트는 UI를 제공하고 useChatRoom 훅을 사용하여 채팅방 기능을 구현한다.
  2. serverUrl 상태를 설정한다.
  3. useChatRoom 훅을 호출하여 서버와 채팅방의 연결을 설정하고 관리한다.
    • roomId와 serverUrl을 인자로 전달






















profile
웹 프론트엔드

0개의 댓글