![](/img/trans.png)
[英]React - Substitute for `setState` Callback in Functional Components?
[英]React functional components, setState and immutability
感覺有點笨,我使用 React 已經 2 年了,一直認為你必須使用setState
和 object 的新副本,以避免改變 state。 但是,此示例對 state 進行了變異,並將setState
與相同的 object 引用一起使用,沒有任何問題。
為什么這行得通?
const { useState } = React;
const Counter = () => {
const [countObject, setCountObject] = useState({count: 0});
const onClick = () => {
countObject.count = countObject.count + 1;
setCountObject(countObject); // mutated object, same reference
}
return (
<div>
<p>You clicked {countObject.count} times</p>
<button onClick={onClick}>
Click me
</button>
</div>
)
}
ReactDOM.render(<Counter />, document.getElementById('app'))
您的 codepen 使用的是 React 16.7 的 alpha 版本。 Hooks 是在 16.8 中發布的,所以要可靠地使用 hooks,你應該使用 16.8 或更高版本(在 React 的非 alpha 版本中):
您可以通過單擊 JavaScript 窗格上代碼筆中的齒輪圖標來更新上述兩個鏈接的版本號。
請注意,以下代碼段使用16.7.0-alpha.2並遇到您遇到的相同問題:
const { useState } = React; const Counter = () => { const [countObject, setCountObject] = useState({count: 0}); const onClick = () => { countObject.count = countObject.count + 1; setCountObject(countObject); } return ( <div> <p>You clicked {countObject.count} times</p> <button onClick={onClick}> Click me </button> </div> ) } ReactDOM.render(<Counter />, document.getElementById('app'))
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.7.0-alpha.2/umd/react.production.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.7.0-alpha.2/umd/react-dom.production.min.js"></script> <div id="app"></div>
但是,將您的版本更改為16.8或更高版本可以解決此問題(在撰寫本文時,我們已更新至 v17.0.2):
const { useState } = React; const Counter = () => { const [countObject, setCountObject] = useState({count: 0}); const onClick = () => { countObject.count = countObject.count + 1; setCountObject(countObject); } return ( <div> <p>You clicked {countObject.count} times</p> <button onClick={onClick}> Click me </button> </div> ) } ReactDOM.render(<Counter />, document.getElementById('app'))
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.0/umd/react.production.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.0/umd/react-dom.production.min.js"></script> <div id="app"></div>
不變性當然很重要,你的代碼可以工作,只是因為修改原來的 object 不會影響功能。 通過共享初始值更改代碼,然后單擊任意按鈕,您會發現有問題。
const { useState } = React;
const Counter = () => {
const value = { count: 0 }
const [countObject, setCountObject] = useState(value);
const [countObject2, setCountObject2] = useState(value);
const onClick = () => {
countObject.count = countObject.count + 1;
setCountObject(countObject);
}
const onClick2 = () => {
countObject2.count = countObject2.count + 1;
setCountObject(countObject2);
}
return (
<div>
<p>You clicked {countObject.count} times</p>
<button onClick={onClick}>
Click me
</button>
<p>You2 clicked {countObject2.count} times</p>
<button onClick={onClick2}>
Click me2
</button>
</div>
)
}
ReactDOM.render(<div><Counter /></div>, document.getElementById('app'))
正如 Nick Parsons 所提到的,這是 Code Pen 中使用的 React 版本的問題。 這是更新了 React 版本的同一支筆,它不起作用(因為它不應該):
https://codepen.io/gfels/pen/QWqZxLP?editors=1111
重新發布 onClick function,因為 StackOverflow 需要帶有代碼筆的代碼
const onClick = () => {
countObject.count = countObject.count + 1;
setCountObject(countObject); // mutated object, same reference
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.