Recoil에서는 상태 업데이트 함수가 순수 함수(또는 로컬 상태를 변경하는 부수 효과)여야 한다.

김현준·2024년 3월 27일
0

리액트 이모저모

목록 보기
4/27

순수 함수와 비순수 함수란?

문제

선요약: Recoil의 상태를 변경하는 함수 내에서 다시 다른 Recoil 상태를 변경하면 무한루프에 빠지는 등 문제 발생

  const [month, setMonth] = useRecoilState(monthAtom);
  const [year, setYear] = useRecoilState(yearAtom);
  const monthOfDays = getLastOfMonth(month);

  const onbeforeClick = () => {
    setMonth((prev) => {
      if (prev <= 1) {
        setYear(prevYear => prevYear - 1)//년도를 바꾼다
        return 12; // 년도를 변경한 후에 prev 값을 수정하지 않음
      } else {
        return prev - 1;
      }
    });
  };

  const onafterClick = () => {
    setMonth((prev) => {
      if (prev >= 12) {
        setYear((prevYear) => prevYear + 1); //년도를 바꾼다
        return 1; // 년도를 변경한 후에 prev 값을 수정하지 않음
      } else {
        return prev + 1;
      }
    });
  };

현재 '달'을 바꾸는 버튼을 눌러 1월이나 12월이 넘어가면 '년도'가 바뀌도록 코드를 짰다. 하지만 저런 에러가 뜬다.

이유는 Recoil에서는 상태 업데이트 함수가 순수 함수여야하기 때문이다.
즉, 동일한 입력에 대해 항상 동일한 결과를 반환해야 한다
ex) function add(1, 2) //3을 반환 or function add(3, 2) //5를 반환

해결방안

1. 상태 업데이트 함수가 순수 함수인지 확인:

  • onbeforeClickonafterClick 함수가 순수 함수인지 확인. 이 함수들은 상태를 변경하고 반환하는 부분에서 어떤 다른 상태 업데이트도 수행하지 않아야 한다.
  • 상태 업데이트 함수 내에서 다른 상태를 변경하지 않도록 주의

2. 상태 업데이트 함수 내에서 다른 상태 업데이트를 피하도록 수정:

  • 상태 업데이트 함수 내에서 다른 상태를 변경하지 않도록 하자. 상태 업데이트 함수는 단순히 상태를 변경하고 반환하는 역할만 수행해야 한다.
  const [month, setMonth] = useRecoilState(monthAtom);
  const [year, setYear] = useRecoilState(yearAtom);
  const [beforYear, setBeforeYear] = useState(false);
  const [afterYear, setAfterYear] = useState(false);
  const monthOfDays = getLastOfMonth(month);

  const onBeforeYear = () => {};

  const onbeforeClick = () => {
    setMonth((prev) => {
      if (prev <= 1) {
        setBeforeYear(true); //이렇게 해결
        return 12;
      } else {
        return prev - 1;
      }
    });
  };

  const onafterClick = () => {
    setMonth((prev) => {
      if (prev >= 12) {
        setAfterYear(true);
        return 1;
      } else {
        return prev + 1;
      }
    });
  };
  useEffect(() => { //useEffect로 특정 데이터 변경시 작동하도록 만듦
    if (beforYear) {
      setYear((prev) => prev - 1);
      setBeforeYear(false);
    }
    if (afterYear) {
      setYear((prev) => prev + 1);
      setAfterYear(false);
    }
  }, [beforYear, afterYear, setYear, setBeforeYear, setAfterYear]);

setAfterYear:

  • setAfterYear(true)는 로컬 상태를 변경하는 부수 효과다.
  • 이는 React 컴포넌트에서 허용되는 동작.
    setYear:
  • setYear은 Recoil의 상태를 변경하는 함수다.
  • Recoil은 상태 변경을 추적하고 관리하기 위해 내부적으로 동작한다.
  • 따라서 순수 함수로 작성되어야 한다.

로컬 상태를 변경하는 부수효과란 함수 실행 중에 발생하는 외부 상태의 변경을 의미

profile
기록하자

0개의 댓글

관련 채용 정보