useState 에 두번째 인자로callback 사용하기

YEONGHUN KO·2022년 3월 4일
0

REACT JS - BASIC

목록 보기
19/31
post-thumbnail
post-custom-banner

클래스안에서는 this.setState에 두번째 인자가 들어가면 이미 첫번째인자에서 업데이트한 state를 두번째 인자에서 받아서 사용가능하다.

그러나 useState에서 setState는 그 기능이 제공되지 않고 있다. 애초에 첫번째 인자만 받아들 일 수 있다.

그러나 여러가지 방법으로 가능하다. useEffect, useRef를 조합해서 customHook을 만들 수 있고, use-state-with-callback 라는 라이브러리를 사용해도 된다.

그럼 알아보자

use-state-with-callback 라이브러리 사용하기

// npm install use-state-with-callback

import useStateWithCallback from 'use-state-with-callback';

const SomeOtherComponent = () => {
  const [count, setCount] = useStateWithCallback(0, count => {
    if (count > 1) {
      document.title = 'Threshold of over 1 reached.';
    } else {
      document.title = 'No threshold reached.';
    }
  });

  return (
    <div>
      <p>{count}</p>

      <button type="button" onClick={() => setCount(count + 1)}>
        Increase
      </button>
    </div>
  );
};

customHook을 만들기

function useStateCallback(initialState) {
  const [state, setState] = useState(initialState);
  const cbRef = useRef(null);

  
  const setStateCallback = useCallback((state, cb) => {
    cbRef.current = cb; 
    setState(state);
  }, []) 
  // useCallback을 이용해서 cb의 reference를 유지해준다
  // 그리고 Ref에 저장한다
  // 그리고 state를 업데이트 한다.

  useEffect(() => {
    if (cbRef.current) {
      cbRef.current(state);
      cbRef.current = null;
    }
  }, [state]);
  // useEffect를 이용해서 setStateCallback을 통해 state가 업데이트 되면 useEffect안에 있는 함수가 실행된다.
  // Ref안에 저장해두었던 두번째 인자 ,callback 함수에 업데이트 된 state를 넣고 실행한다.
  // 그다음 ReF를 초기화 시켜 다음 들어올 callback을 받을 준비를 한다.

  return [state, setStateCallback];
}


const App = () => {
  const [state, setState] = useStateCallback(0);

  const handleClick = () =>
    setState(
      prev => prev + 1,
      // important: use `s`, not the stale/old closure value `state`
      s => console.log("I am called after setState, state:", s)
    );

  return (
    <div>
      <p>Hello Comp. State: {state} </p>
      <button onClick={handleClick}>Click me</button>
    </div>
  );
}

ReactDOM.render(<App />, document.getElementById("root"));

짠! 자세한 설명은 주석을 참고!

적극적으로 customHook을 만들어볼 생각을 하자.

독립적으로 state를 관리해보자!

profile
'과연 이게 최선일까?' 끊임없이 생각하기
post-custom-banner

0개의 댓글