簡體   English   中英

在事件處理程序中進行 setState 調用后,React 何時重新渲染

[英]When does React re-render after a setState call made inside an event handler

從反應文檔:

https://reactjs.org/docs/state-and-lifecycle.html

State 更新可能是異步的

React 可以將多個 setState() 調用批處理到單個更新中以提高性能。

這完全有道理。 如果您有類似下面的 function 之類的東西,那么在每個setState調用上重新渲染都會非常低效

const [state1,setState1] = useState(false);
const [state2,setState2] = useState(false);
const [state3,setState3] = useState(false);

function handleClick() {
  setState1(true);
  setState2(true);
  setState3(true);
}

因此,在上述情況下,我希望 React 將所有 3 個setState調用批處理到一個重新渲染中。 它正是這樣做的!

但我想知道的是:

一旦handleClick完成,是否保證在handleClick完成運行后立即發生重新渲染? 我的意思是立即同步,例如立即同步?

從我構建的這個片段來看,這似乎是真的。 handleClick完成后,React 將同步應用更新(重新渲染)。 如果我假設錯誤,請糾正我。

請參見下面的片段:

  • 盡可能快地點擊 3 倍
  • handleClick將調用setState並將記錄當前的props.counter
  • App上有一個昂貴的循環,因此重新渲染需要很長時間
  • 您將能夠比 React 重新渲染整個應用程序更快地單擊
  • 但是你會看到props.counter每次都不一樣,沒有任何重復,即使你點擊多次真的很快
  • 這意味着一旦您的第二次點擊被處理(由於昂貴的循環需要一段時間),React 已經重新渲染了整個事情,並且已經使用來自props.counter的新值重新創建了handleClick function counter更新了 state。
  • 嘗試快速單擊 5 次,您會發現行為是相同的。

問題

當在事件處理程序 function 中進行setState調用時,一旦該處理程序 function 完成運行,是否保證在處理程序完成后立即(同步)重新渲染?

 function App() { console.log("App rendering..."); const [counter, setCounter] = React.useState(0); // AN EXPENSIVE LOOP TO SLOW DOWN THE RENDER OF 'App' for (let i = 0; i < 100000; ) { for (let j = 0; j < 10000; j++) {} i = i + 1; } return <Child counter={counter} setCounter={setCounter} />; } function Child(props) { console.log("Child rendering..."); // THIS FUNCTION WILL CALL 'setState' // AND WILL ALSO LOG THE CURRENT 'props.counter' function handleClick() { props.setCounter(prevState => prevState + 1); console.log(props.counter); } return ( <React.Fragment> <div>Counter: {props.counter}</div> <button onClick={handleClick}>Click</button> </React.Fragment> ); } const rootElement = document.getElementById("root"); ReactDOM.render(<App />, rootElement);
 <script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.3/umd/react.production.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.3/umd/react-dom.production.min.js"></script> <div id="root"/>

一旦handleClick完成,是否保證在handleClick完成運行后立即發生重新渲染? 我的意思是立即,就像同步立即

對於某些事件,包括click ,React 保證組件將在另一個事件發生之前重新渲染。 (對於mousemove等其他事件,情況並非如此。)您可以在此處找到哪些事件。 當前的術語似乎是DiscreteEvent是存在此保證的那些,而UserBlockingEvent是不保證存在的那些。 很可能在當前實現中,這意味着它在事件處理結束時同步完成¹,但我認為保證沒有那么具體。

在 Twitter 上從 Dan Abramov 那里了解到這一點(他對事件使用了較舊的術語)。


¹ 編輯:事實上,Joseph D. 在他的回答中指出了 Dan Abramov 的評論,他說現在是這樣,但也說“這是實現細節,可能會在未來的版本中改變”

是否保證在處理程序完成后立即(同步)重新渲染?

是的onClick

正如 Dan Abramov 所指出的

React 批處理在 React 事件處理程序期間完成的所有 setStates,並在退出其自己的瀏覽器事件處理程序之前應用它們

暫無
暫無

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

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