React.js - 功能组件中的状态未更新[重复]

Posted

技术标签:

【中文标题】React.js - 功能组件中的状态未更新[重复]【英文标题】:React.js -- state not updating in functional component [duplicate] 【发布时间】:2021-12-09 08:06:32 【问题描述】:

我有一个功能组件,它带有一个名为“checked”的状态钩子,它是一个用于复选框列表的布尔数组。单击复选框时,我有一个更新状态的事件处理程序,因此复选框将呈现一个复选或一个空框。

根据我的函数中的 console.logs,状态正在更新,但复选框在浏览器中没有响应,并且开发工具确认状态没有更新。如果我使用开发工具手动切换状态,复选框就可以正常工作,所以我认为这是状态不更新的问题。任何建议将不胜感激!

import React,  useState, useContext  from 'react';

export default function MessengerCheckboxes() 
 const [checked, setChecked] = useState([false, false, false]);

...

 const handleChangeChild = (event) => 
   console.log('Currently state is: ' + checked); // Currently state is: [false, false, false]

   let index = parseInt(event.target.id.slice(0, 1));
   let localChecked = checked; //
   localChecked[index] = !checked[index];
    
   console.log('State should be: ' + localChecked); //State should be: [true, false, false] [[for example]]
   setChecked(localChecked);
    
   setTimeout(() =>  // Added setTimeout for troubleshooting to make sure I wasn't calling state too quickly after setting it
       console.log('State is now: ' + checked); // State is now: [true, false, false] [[but won't trigger re-render and dev tools show state is [false, false, false]]
   , 1 * 1000);
 ;


Image of my console.log

Image of my dev tools

非常感谢您!

【问题讨论】:

另发jsx 这不是你应该更新状态的方式。不要通过执行 array[idx] = true 来改变现有数组。您必须使用 setChecked([...]) 重新分配整个数组。了解可变和不可变对象 你正在改变状态。不要改变状态。 谢谢大家!! 【参考方案1】:

你不应该那样更新状态。

在这种情况下,需要一个更复杂的状态对象。我喜欢使用一个对象来保持列表中每个项目的状态。 检查此链接:https://codesandbox.io/s/checkbox-state-https-***-com-questions-69680938-react-js-state-not-updating-in-functional-component-di0dd

import "./styles.css";
import  useState  from "react";

export default function App() 
  // 1.
  const stateObj = 
    cb1: false,
    cb2: false,
    cb3: false
  ;
  const [cbState, setCbState] = useState(stateObj);
  const handleCb = (event) => 
    console.log(event.target.name, event.target.checked);
    // 4.
    setCbState( ...cbState, [event.target.name]: event.target.checked );
  ;
  return (
    <div>
      <input
        type="checkbox"
        name="cb1" // 2.
        onChange=handleCb
        value=cbState["cb1"] // 3.
      />
      <input
        type="checkbox"
        name="cb2"
        onChange=handleCb
        value=cbState["cb2"]
      />
      <input
        type="checkbox"
        name="cb3"
        onChange=handleCb
        value=cbState["cb3"]
      />
    </div>
  );

所以要带走,分步骤:

    创建/准备状态对象 - 键将用作 html 元素的名称 为 html 元素设置名称属性 - 使用与 1 相同的键。 为 html 元素设置值属性 - 使用 state['key'] 的括号表示法。这就是你实现controlled components的方式 以持久化现有数据/值 (using spread operator) + 更新 (bracket notation for accessing the properties) 的方式设置状态。在此示例中,我们使用事件 namechecked 属性来实现它。

【讨论】:

谢谢你,斯特凡!这成功了。我只记得使用引用而不是值的对象,并且会在以后更多地记住这一点。谢谢!【参考方案2】:

好吧,您应该已经阅读了不应该改变状态的 cmets。所以为了处理这种情况,我通常会这样做:-

setChecked(data => (
      ...data,
      [ind]: !checked[ind]
))

附: - 阅读有关处理状态的不同方法,从长远来看,它会对您有很大帮助。 :)

【讨论】:

以上是关于React.js - 功能组件中的状态未更新[重复]的主要内容,如果未能解决你的问题,请参考以下文章

React.js:在更改状态的输入字段中单击取消时如何返回先前的状态值[重复]

未处理的拒绝:操作未定义React js和Redux

如何在 React.js 的另一个组件中更新组件状态变量的值?

React JS:调用 setState 后组件未更新

为啥 getElementsByClassName 在 React 功能组件中返回未定义?

无法将数据从子功能组件传递到反应父组件(React.js)[重复]