function useHandleURL(mode, page) {
const [is_page_hidden, set_is_page_hidden] = useState(true);
...
set_is_page_hidden(true);
}
以上將導致無限重新渲染。
我必須通過這樣做來解決:
function useHandleURL(mode, page) {
const [is_page_hidden, set_is_page_hidden] = useState(true);
...
if (!is_page_hidden) {
set_is_page_hidden(true);
}
}
這不是 React 組件內部的行為。在組件內部,如果我將 useState 設定為truewhen it already true,則不會導致重新渲染。
有人可以確認這種行為并解釋為什么它會導致 Hook 內部無限重新渲染而不是 Component 嗎?
uj5u.com熱心網友回復:
我可以確認在函陣列件的主體中使用相同的確切代碼渲染回圈與在自定義鉤子中時相同。問題是狀態設定器的無條件呼叫。
請參閱useState 退出狀態更新
如果您將 State Hook 更新為與當前狀態相同的值,React 將退出而不渲染子級或觸發效果。(React 使用Object.is 比較演算法。)
請注意,React 可能仍需要在退出之前再次渲染該特定組件。這不應該是一個問題,因為 React 不會不必要地“深入”到樹中。如果您在渲染時進行昂貴的計算,您可以使用
useMemo.
另請注意,“React 可能仍需要在退出之前再次渲染該特定組件。” 意味著再運行一次渲染函式,而不是“再一次渲染到 DOM”,所以任何意想不到的副作用,比如將另一個狀態更新加入佇列都是有問題的。一個函陣列件的整個函式體就是渲染函式。
請考慮以下代碼:
function App() {
const [is_page_hidden, set_is_page_hidden] = React.useState(true);
const handler = () => set_is_page_hidden(true);
React.useEffect(() => {
console.log("RENDERED!");
});
return <button type="button" onClick={handler}>Click</button>;
}
const rootElement = document.getElementById("root");
ReactDOM.render(
<React.StrictMode>
<App />
</React.StrictMode>,
rootElement
);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/17.0.2/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/17.0.2/umd/react-dom.production.min.js"></script>
<div id="root" />
我們有條件地將具有相同值的狀態更新加入佇列,并注意到沒有觸發任何重新渲染,這是通過useEffect每 1 個渲染周期記錄 1 個效果的鉤子來衡量的。
結論
有條件地將狀態更新入隊是正確的。
function useHandleURL(mode, page) {
const [is_page_hidden, set_is_page_hidden] = useState(true);
...
if (!is_page_hidden) {
set_is_page_hidden(true);
}
}
更新
I just realized that it's not necessarily the unconditional state update, but more the unintentional side-effect.
Render loops
function App() { const [is_page_hidden, set_is_page_hidden] = React.useState(true); set_is_page_hidden(true); return ...; }Stable, no render looping
function App() { const [is_page_hidden, set_is_page_hidden] = React.useState(true); React.useEffect(() => { console.log("RENDERED!"); set_is_page_hidden(true); }); return "Stackoverflow is awesome."; } const rootElement = document.getElementById("root"); ReactDOM.render( <React.StrictMode> <App /> </React.StrictMode>, rootElement );<script src="https://cdnjs.cloudflare.com/ajax/libs/react/17.0.2/umd/react.production.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/17.0.2/umd/react-dom.production.min.js"></script> <div id="root" />
In the stable version the state update is an intentional state update as an intentional side-effect, so no rerenders are triggered since the state value is the same as the previous render cycle.
轉載請註明出處,本文鏈接:https://www.uj5u.com/yidong/426580.html
標籤:javascript 反应 反应钩子 使用状态 反应组件
