reactjs - 如果使用 Hook 的初始 setValue 方法,React 不会更新值
问题描述
我使用这种方法创建了一个简约的应用程序npx create-react-app
。我创建了一个functional component
并尝试了一个钩子的旧setValue 方法是否useState
更新了钩子维护的值。
listOfSetValueMethods
因此,我创建了一个包含所有setValue
方法的数组。在myButtonClick()
方法中我使用了第 setValue
一种方法来更新钩子的值:它不起作用:react 不会重新渲染任何东西: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>
);
}
calllistOfSetValueMethods[0](scopeId+1)
和 listOfSetValueMethods[X](scopeId+1)
which和有什么不一样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!App.js:13 scopeId: 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)
}
推荐阅读
- json - Spring-Kafka 无法将 AVRO GenericData.Record 转换为 Acknowledgement
- javascript - 如何在Javascript中检索函数之外的数据?
- sql - CTE 递归以获取具有空级别的层次结构级别
- javascript - 无法在端口 80 上服务 Express + React 应用程序
- javascript - 单击另一个下拉框时如何关闭任何打开的下拉框?
- postgresql - 如何将 Oracle Next_Day 函数转换为 Postgres SQL?
- python - Python - 链表问题和相关性
- c# - ASP.NET Core EventLog 未注册
- bluetooth-lowenergy - 低功耗蓝牙模糊测试
- azure - Azure 函数 - 当前 Azure 资源名称