首页 > 解决方案 > 如果使用 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

标签: reactjsreact-hooks

解决方案


我不知道您要做什么以及为什么要让它变得如此困难。您在每次渲染时不断将 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)
}

推荐阅读