簡體   English   中英

React hooks 的奇怪行為:延遲數據更新

[英]Strange behavior of React hooks: delayed data update

奇怪的行為:我希望第一個和第二個 console.log 顯示不同的結果,但它們顯示相同的結果,並且僅在下次單擊時更改值。 我應該如何編輯我的代碼以使值不同?

 function App() { const [count, setCount] = React.useState(false); const test = () => { console.log(count); //false setCount(!count); console.log(count); //false }; return ( <div className="App"> <h1 onClick={test}>Hello StackOverflow</h1> </div> ); } const rootElement = document.getElementById("root"); ReactDOM.render(<App />, rootElement);
 <script crossorigin src="https://unpkg.com/react@16/umd/react.development.js"></script> <script crossorigin src="https://unpkg.com/react-dom@16/umd/react-dom.development.js"></script> <div id="root"></div>

你可以在這里看到一個工作示例: https : //codesandbox.io/s/wz9y5lqyzk

狀態更新是異步的,因此如果您使用 Hooks,您可以使用useEffect在更新后收到通知。

下面是一個例子:

https://codesandbox.io/s/wxy342m6l

如果您使用的是 React 組件的 setState,則可以使用回調

this.setState((state) => ({count: !state.count}), () => console.log('Updated', this.state.count));

如果您需要狀態值,請記住使用回調來更新狀態。

狀態更新是異步的 您從useState獲得的setCount函數無法神奇地伸出並更改您的count常量的值。 一方面,它是一個常數。 另一方面, setCount無權訪問它。 相反,當您調用setCount ,您的組件函數將再次被調用,並且useState將返回更新后的計數。

現場示例:

 const {useState} = React; function Example() { const [count, setCount] = useState(false); const test = () =>{ setCount(!count); // Schedules asynchronous call to Example, re-rendering the component }; return ( <div className="App"> <h1 onClick={test}>Hello CodeSandbox</h1> <div>Count: {String(count)}</div> </div> ); } ReactDOM.render(<Example />, document.getElementById("root"));
 <div id="root"></div> <script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.4/umd/react.production.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.4/umd/react-dom.production.min.js"></script>

如果您需要在count更改時執行一些副作用,請使用useEffect

useEffect(() => {
  console.log(`count changed to ${count}`);
}, [count]);

請注意,我們告訴useEffect僅在count更改時調用我們的回調,這樣如果我們有其他狀態,我們的回調就不會不必要地運行。

現場示例:

 const {useState, useEffect} = React; function Example() { const [count, setCount] = useState(false); const test = () =>{ setCount(!count); // Schedules asynchronous call to Example, re-rendering the component }; useEffect(() => { console.log(`count changed to ${count}`); }, [count]); return ( <div className="App"> <h1 onClick={test}>Hello CodeSandbox</h1> <div>Count: {String(count)}</div> </div> ); } ReactDOM.render(<Example />, document.getElementById("root"));
 <div id="root"></div> <script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.4/umd/react.production.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.4/umd/react-dom.production.min.js"></script>

setState鈎子不會直接更新組件中的值。 它更新它的內部狀態,導致組件的重新渲染,然后返回您分配給count的新狀態值。

當您在test console.log(count) ,您會顯示count的當前值,即舊值(更新前)。 如果您將console.log()移動到渲染,您將看到新值:

 const { useState } = React; const Component = () => { const [count, setCount] = useState(false); const test = () => { console.log('before: ', count); setCount(!count) } console.log('after: ', count); return ( <div className="App"> <button onClick={test}>Click</button> </div> ); } ReactDOM.render( <Component />, demo );
 <script crossorigin src="https://unpkg.com/react@16/umd/react.development.js"></script> <script crossorigin src="https://unpkg.com/react-dom@16/umd/react-dom.development.js"></script> <div id="demo"></div>

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM