공부공부/React

[react 공식문서] 29 Removing Effect Dependencies

고생쨩 2024. 2. 14. 08:05
728x90

리액트 공식문서 학습기록
https://react.dev/learn

Removing Effect Dependencies

종속성은 코드와 일치해야함

Effect는 반응값에 '반응’함. 그래서 linter는 그게 종속성에 있는지 확인함. 고로 linter가 시키는대로 하셈.

종속성을 제거하고 싶으면

[] 빈배열 던지셈

종속성을 변경하려면 코드를 고치셈

  1. Effect의 코드를 변경하거나 반응값이 선언되는 방식을 변경
  2. linter가 시키는 대로 종속성 조정
  3. 맘에 안 들면 1번으로 돌아가서 코드 변경

불필요한 의존성 제거

  1. 코드를 이벤트 핸들러로 이동해야하는지 -> 꼭 Effect여야하는지 여부
  2. Effect가 관련없는 일을 하고 있는가? -> 별도 통신을 한다던지
  3. 다음 상태를 계산하기 위해 일부 상태를 읽고있는지 -> 업데이트 기능을 전달하셈(🤔 잘 모르겠고)

변경 사항에 '반응’하지 않고 값을 읽고 싶을때

  • 반응하면 안되는 부분을 Effect에서 추출하자
  • props의 경우 useEffectEvent로 래핑하자
function ChatRoom({ roomId, onReceiveMessage }) {
  const [messages, setMessages] = useState([]);

  const onMessage = useEffectEvent(receivedMessage => {
    onReceiveMessage(receivedMessage);
  });

  useEffect(() => {
    const connection = createConnection();
    connection.connect();
    connection.on('message', (receivedMessage) => {
      onMessage(receivedMessage);
    });
    return () => connection.disconnect();
  }, [roomId]); // ✅ All dependencies declared
  // ...

일부 반응값이 의도치 않게 변경될때

  • 종속성
  • 상수(값, 함수)를 컴포넌트 외부로 이동
  • 내부에 객체를 생성하여 사용 -> 외부 편집 시 다시 동작하지 않음.
const serverUrl = 'https://localhost:1234';

function ChatRoom({ roomId }) {
  const [message, setMessage] = useState('');

  useEffect(() => {
    const options = {
      serverUrl: serverUrl,
      roomId: roomId
    };
    const connection = createConnection(options);
    connection.connect();
    return () => connection.disconnect();
  }, [roomId]); // ✅ All dependencies declared
  // ...

과제 1

재렌더링 막기
👉 setter로 상태값을 변경하지말고 updater 함수 사용

import { useState, useEffect } from 'react';

export default function Timer() {
  const [count, setCount] = useState(0);

  useEffect(() => {
    console.log('✅ Creating an interval');
    const id = setInterval(() => {
      console.log('⏰ Interval tick');
      setCount(c => c + 1);
    }, 1000);
    return () => {
      console.log('❌ Clearing an interval');
      clearInterval(id);
    };
  }, []);

  return <h1>Counter: {count}</h1>
}

과제 2

duration 변경시 재렌더링 막기
👉 useEffectEvent를 쓰자

import { useState, useEffect, useRef } from 'react';
import { FadeInAnimation } from './animation.js';
import { experimental_useEffectEvent as useEffectEvent } from 'react';

function Welcome({ duration }) {
  const ref = useRef(null);

  const onAppear = useEffectEvent(animation => {
    animation.start(duration);
  });

  useEffect(() => {
    const animation = new FadeInAnimation(ref.current);
    onAppear(animation);
    return () => {
      animation.stop();
    };
  }, []);

  return (
    <h1
      ref={ref}
      style={{
        opacity: 0,
        color: 'white',
        padding: 50,
        textAlign: 'center',
        fontSize: 50,
        backgroundImage: 'radial-gradient(circle, rgba(63,94,251,1) 0%, rgba(252,70,107,1) 100%)'
      }}
    >
      Welcome
    </h1>
  );
}

export default function App() {
  const [duration, setDuration] = useState(1000);
  const [show, setShow] = useState(false);

  return (
    <>
      <label>
        <input
          type="range"
          min="100"
          max="3000"
          value={duration}
          onChange={e => setDuration(Number(e.target.value))}
        />
        <br />
        Fade in duration: {duration} ms
      </label>
      <button onClick={() => setShow(!show)}>
        {show ? 'Remove' : 'Show'}
      </button>
      <hr />
      {show && <Welcome duration={duration} />}
    </>
  );
}

과제 3

채팅 재접속 막기
👉 종속성을 객체로 전달하지 말고 따로따로 전달해라

import { useEffect } from 'react';
import { createConnection } from './chat.js';

export default function ChatRoom({ options }) {
  const { roomId, serverUrl } = options;
  useEffect(() => {
    const connection = createConnection({
      roomId: roomId,
      serverUrl: serverUrl
    });
    connection.connect();
    return () => connection.disconnect();
  }, [roomId, serverUrl]);

  return <h1>Welcome to the {options.roomId} room!</h1>;
}

과제 4

채팅 재접속 막기
👉 종속성을 똑바로

import { useState, useEffect } from 'react';
import { experimental_useEffectEvent as useEffectEvent } from 'react';
import {
  createEncryptedConnection,
  createUnencryptedConnection,
} from './chat.js';

export default function ChatRoom({ roomId, isEncrypted, onMessage }) {
  const onReceiveMessage = useEffectEvent(onMessage);

  useEffect(() => {
    function createConnection() {
      const options = {
        serverUrl: 'https://localhost:1234',
        roomId: roomId
      };
      if (isEncrypted) {
        return createEncryptedConnection(options);
      } else {
        return createUnencryptedConnection(options);
      }
    }

    const connection = createConnection();
    connection.on('message', (msg) => onReceiveMessage(msg));
    connection.connect();
    return () => connection.disconnect();
  }, [roomId, isEncrypted]);

  return <h1>Welcome to the {roomId} room!</h1>;
}

이 포스팅은 쿠팡 파트너스 활동의 일환으로, 이에 따른 일정액의 수수료를 제공받습니다.