如果使用 Hook 的初始 setValue 方法,React 不会更新值



我使用npx create-react-app方法创建了一个简约的应用程序。我创建了一个functional component并尝试了useState钩子的setValue 方法是否更新了钩子维护的值。

因此,我创建了一个包含所有setValue方法的数组listOfSetValueMethods。在myButtonClick()方法中,我使用第一个setValue方法来更新钩子的值:它不起作用:反应不会重新渲染任何内容:listOfSetValueMethods[0](scopeId+1);。如果我使用任何其他setValue方法,它确实有效

var myCounter=0;
var listOfSetValueMethods=[];
function MyComponent() {
const [currentScopeId,setValue]=useState(-1);
listOfSetValueMethods.push(setValue);
let scopeId=myCounter++;
console.log("scopeId: " + scopeId);
function myButtonClick(){
if(listOfSetValueMethods.length>0){
listOfSetValueMethods[0](scopeId+1); //does not work
//works: listOfSetValueMethods[1](scopeId+1); 
console.log("setted value to:" + (scopeId+1) + ", current value in scope:" + currentScopeId);
}else{
setValue(scopeId);
}
}
return (
<div>
<b onClick={()=>{myButtonClick()}}> id: {currentScopeId}</b> <br />
</div>
);
} 

打电话给listOfSetValueMethods[0](scopeId+1)listOfSetValueMethods[X](scopeId+1)有什么区别,从而X>0

控制台输出:

scopeId: 0
App.js:13 scopeId: 1
App.js:19 setted value to:2, current value in scope:-1
App.js:13 scopeId: 2
App.js:13 scopeId: 3
App.js:19 setted value to:2, current value in scope:-1
App.js:13 scopeId: 4

因此,当前范围 ID 保持在 -1! 应用.js:13 范围 ID: 5

我不知道你想做什么,为什么你让它变得如此困难。你不断在每个渲染上将 setValue 推送到 listOfSetValueMethods,但 setValue 永远不会改变,所以没有意义。

您正在记录一个过时的闭包,所以也许这就是您所说的"不起作用"的意思。

这是您的代码,并显示每次渲染时 setValue 都是相同的:

var myCounter = 0;
var listOfSetValueMethods = [];
function App() {
const [currentScopeId, setValue] = React.useState(-1);
listOfSetValueMethods.push(setValue);
let scopeId = myCounter++;
console.log('scopeId: ' + scopeId);
function myButtonClick() {
//this works just fine
listOfSetValueMethods[0](scopeId + 1);
console.log(
'setted value to:' +
(scopeId + 1) +
', current value in scope:' +
currentScopeId //this logs a stale closure
);
}
return (
<div>
are all items in listOfSetValueMethods the same:
{listOfSetValueMethods.every(
(item) => item === setValue
)+""}
<button onClick={() => {myButtonClick()}}>
id: {currentScopeId}
</button>
</div>
);
}
ReactDOM.render(<App />, document.getElementById('root'));
<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>
<div id="root"></div>

因此,与其让这些 myCounter 和 listOfSetValueMethods 在渲染该组件的多个实例时会中断,不如这样做:

function myButtonClick() {
setValue(value=>value+1)
}

相关内容

  • 没有找到相关文章

最新更新