[TodayError] useState는 왜 바로 상태를 변화시키지 않을까?

송은석·2021년 6월 8일
2

TodayError

목록 보기
5/5
post-thumbnail

컴포넌트들을 만드는데 로직이 생각대로 실행되지 않았다. 원하지도 않는 함수가 멋대로 실행되기도 하고..ㅠ

어느 부분이 문제인지 되짚어 보기 위해 모든 콜백 함수 마다 콘솔 로그를 넣어서 실행해보았다.

그러다가 발견한 문제?!! useState의 setState함수를 통해 상태를 업데이트하고 난 바로 다음 줄에 콘솔로그가 찍혔는데, 원래 상태가 전혀 바뀌지 않은 상태로 찍혔다. 다음의 코드이다ㅠ

const Test = () => {
  const [modal, setModal] = useState(false);

  const modalToggle = useCallback(() => {
    console.log('modal');
    console.log(modal);
    setModal(!modal);
    console.log('modal');
    console.log(modal);
  }, [modal]);

  return (
    <div>
      <button onClick={modalToggle}>모달 생성</button>
      {modal && <Modal modalToggle={modalToggle} status={modal} />}
    </div>
  );
};

export default Test;

그래서 관련된 내용을 찾아보다가, 다음의 스택플로우 글을 보게 되었다.

https://stackoverflow.com/questions/61054275/usestate-with-boolean-value-in-react

나와 같은 고민을 한 사람이 질문을 한 것인데, 답변은 다음과 같다.
useState나 훅은 비동기로 실행되는 함수들이므로 함수 실행 이후 바로 콘솔을 찍으면 안된다는 것이다.
그래서 바로 안찍고 setTime함수로 5초를 주고 콘솔로그를 실행하게 했다.

...

그래도 안됐다. 뭐가 문제지^^ 콜백 구간에 setState, setTime 모두 같이 갇혀있는 것일까^^

https://reactjs.org/docs/state-and-lifecycle.html#state-updates-may-be-asynchronous

추가로 다음의 react docs도 좀 살펴보았다.

결국 내가 원하는 대로 setState의 결과를 받아보고 싶다면 useEffect를 쓰라는 말이 나왔다.
리액트는 각 상태들을 업데이트한 뒤에 이 훅을 실행하기 때문이다^^
말 그대로 state와 다른 훅들이 작업해놓은 후의 effect를 가지고 쓰는 것이다.

휴..

const Test = () => {
  const [modal, setModal] = useState(false);

  const modalToggle = useCallback(() => {
    console.log('modal');
    console.log(modal);
    setModal(!modal);
    console.log('modal');
    console.log(modal);
  }, [modal]);

  useEffect(() => {
    console.log(modal);
  }, [modal]);

  return (
    <div>
      <button onClick={modalToggle}>모달 생성</button>
      {modal && <Modal modalToggle={modalToggle} status={modal} />}
    </div>
  );
};

이제.. 콘솔에 잘 찍힌다.

결론적으로 useState나 훅스들은 비동기로 함수를 실행시키므로 즉각적으로 결과가 반영되지 않을 수 있다는 것을 알게 되었다. 따라서 함수 실행 이후의 결과를 통해 로직을 이어나가고 싶다면 useEffect를 활용해야 하겠다. useEffect 끝의 [ ]에 사용할 상태를 넣어주는 것도 잊지 말고!

profile
Done is better than perfect🔥

0개의 댓글