我使用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)
}