programing

반응 - useState - setTimeout 함수에 최신 상태 값이 없는 이유는 무엇입니까?

sourcejob 2023. 3. 15. 19:33
반응형

반응 - useState - setTimeout 함수에 최신 상태 값이 없는 이유는 무엇입니까?

최근에 리액트 훅 작업을 하다가 한 가지 문제/의심 때문에 곤혹스러웠습니까?

다음은 문제를 재현하기 위한 기본적인 구현입니다.여기서 토글하겠습니다flag(상태) 버튼을 클릭했을 때의 변수.

  const [flag, toggleFlag] = useState(false);
  const data = useRef(null);
  data.current = flag;

  const _onClick = () => {
    toggleFlag(!flag);
    // toggleFlag(!data.current); // working

    setTimeout(() => {
      toggleFlag(!flag); // does not have latest value, why ?
      // toggleFlag(!data.current); // working
    }, 2000);
  };

  return (
    <div className="App">
      <button onClick={_onClick}>{flag ? "true" : "false"}</button>
    </div>
  );

useRef나 useReducer를 사용하는 등 이 문제를 해결할 다른 방법을 찾았습니다만, 이것이 맞습니까, 아니면 useState만으로 해결할 수 있는 다른 방법이 있습니까?

또한 set Timeout 내에서 왜 오래된 상태 값을 얻었는지 설명해 주시면 감사하겠습니다.

샌드박스 URL - https://codesandbox.io/s/xp540ynomo

이는 JavaScript에서의 클로저 동작으로 요약됩니다.주어진 기능setTimeout을 얻을 수 있다flag초기 렌더링에서 변수, 이후flag변환되지 않습니다.

대신 함수를 인수로 지정할 수 있습니다.toggleFlag이 함수는 올바른 값을 얻을 수 있습니다.flagvalue as 인수 및 이 함수에서 반환되는 것은 상태를 대체하는 것입니다.

const { useState } = React;

function App() {
  const [flag, toggleFlag] = useState(false);

  const _onClick = () => {
    toggleFlag(!flag);

    setTimeout(() => {
      toggleFlag(flag => !flag)
    }, 2000);
  };

  return (
    <div className="App">
      <button onClick={_onClick}>{flag ? "true" : "false"}</button>
    </div>
  );
}

ReactDOM.render(<App />, document.getElementById("root"));
<script src="https://unpkg.com/react@16/umd/react.development.js"></script>
<script src="https://unpkg.com/react-dom@16/umd/react-dom.development.js"></script>

<div id="root"></div>

주어진 기능setTimeout을 얻을 수 있다flag에서 변수_onClick기능._onClick함수는 렌더링할 때마다 생성되며 이 함수의 값을 "저장"합니다.flag변수가 이 렌더에 표시됩니다.

function App() {
  const [flag, toggleFlag] = useState(false);
  console.log("App thinks that flag is", flag);

  const _onClick = () => {
    console.log("_onClick thinks that flag is", flag);
    toggleFlag(!flag);

    setTimeout(() => {
      console.log("setTimeout thinks that flag is", flag);
    }, 100);
  };

  return (
    <div className="App">
      <button onClick={_onClick}>{flag ? "true" : "false"}</button>
    </div>
  );
}

콘솔:

App thinks that flag is false

_onClick thinks that flag is false
App thinks that flag is true
setTimeout thinks that flag is false

_onClick thinks that flag is true
App thinks that flag is false
setTimeout thinks that flag is true

언급URL : https://stackoverflow.com/questions/55198517/react-usestate-why-settimeout-function-does-not-have-latest-state-value

반응형