web-dev-qa-db-ja.com

SetIntervalは更新された状態を表示していません

setInterval関数を呼び出す前に、状態をtrueに設定しました。しかし、useEffectフックが状態の新しい値でトリガされていても、setInterval関数には反映されていません。

enter image description here コードサンドボックスここ: https://jsfiddle.net/6e05tc2l/3/

let interval;
const Component = () => {
  React.useEffect(() => {
    console.log('State updated to', state);
  });
  const [state, setState] = React.useState(false);
  const on = () => {
    setState(true);
    interval = setInterval(() => {
      console.log(state);
    }, 1000);
    }
  const off = () => {
    setState(false);
    clearInterval(interval);
  }
  const toggle = () => state ? off() : on()

  return (<div>
    <button onClick={toggle}>Toggle State</button>
   </div>);
}

ReactDOM.render(
  <Component />,
  document.getElementById('container')
);
 _

それが更新されたら、状態の新しい価値を使用してはいけませんか?

4
acesmndr

UseEffectに渡す関数に渡す関数内の値は、それに合格する関数の新しい定義を使用するため、すべてのレンダリングで更新されます。

しかしSetIntervalに渡された関数は一度定義され、それは古い状態の状態の古い値を覆います。まだ更新されていない。

クロージャはフックで難しいですが、実現することは、UseEffectが各レンダリングに対して新しい関数を作成し、それ故、関数が新鮮な状態値を閉じるたびに作成されるということです。

その後、トリックはUseEffect自体内でSetInterval関連のコードを呼び出すことであり、それ自体は状態の変化の値に依存します

React.useEffect(() => {
  if(state) {

    interval = setInterval(() => {
      console.log(state);
    }, 1000);
  } else {
    clearInterval(interval);
  }

}, [state]);
 _

それとも、あなたのためにこれらの詳細を大事にするUSEIntervalフックを使用してください。

4
Mukesh Soni

私はReactJSエキスパートではありませんが、ロギングしているstateが更新されず、更新されていないので更新されません。 React.useState(false)があなたの状態を与えている方法では、あなたの間隔関数でそれを使うべきです。

ここに説明しようとしているものの例です。

const object = { value: false }


const notRefreshed = object.value // here we are copying the value

const interval = setInterval(() => {
  const refreshed = object.value // here we are using the reference to copy the latest value
  console.log("refreshed", refreshed)
  console.log("notRefreshed", notRefreshed)
}, 500)


setTimeout(() => object.value = true, 1600)

setTimeout(() => clearInterval(interval), 2600) _
0
Ulysse BN