使用对象数组中的钩子更新状态

时间:2020-08-14 23:06:14

标签: javascript reactjs react-hooks state

我想在我的对象中将active更改为true,在控制台日志中,我具有状态的更新版本,但是我无法更新状态本身,我觉得这是错误的做法。任何帮助都将是非常棒的谢谢,可以肯定的是,某处有类似的帖子,但是我没有找到任何东西。

const [components, setComponents] = useState([
  {
    compName: "Weather",
    path: 'weather',
    active: false
  },
  {
    compName: "Tasks",
    path: 'tasks',
    active: false
  },
])
                                                      

 function onActivateHandler(){
      setComponents((prevComponents) => {
        const copy = [...prevComponents]
        let newState = {...copy[1]}
        newState.active = true
        console.log(newState)
    
        return  {...prevComponents}
      })
 }

2 个答案:

答案 0 :(得分:0)

我认为您只需要为整个数组生成一个新引用即可。

我注意到的另一件事是您正在从setComponents()函数返回一个对象。由于状态变量components是一个数组,我认为您需要返回一个数组。

另外,将onActivateHandler()方法编写为箭头函数,以将其绑定到组件上下文,以防万一,通常是您要执行的操作。

我会这样写(我切换活动值正好演示):

const myComponent = () => {
    const [components, setComponents] = useState([
        {
           compName: "Weather",
           path: "weather",
           active: false,
        },
        {
           compName: "Tasks",
           path: "tasks",
           active: false,
        },
    ]);

    const onActivateHandler = () => {
        setComponents((prevComponents) => {
           // update the array reference
           const newState = [...prevComponents];
           newState[1].active = !newState[1].active;

           // Your state variable is an array,
           // so you need to return an array
           return [...prevComponents];
        });
    };

    return (
        <>
            <button onClick={onActivateHandler}>Click</button>
            <div>{components[1].active ? 'active' : 'inactive'}</div>
        </>
    )
};

正如下面的lawrence-witt所述,在某些情况下,未在新数组内创建新对象可能导致不重新渲染,但是在您的简单情况下,上面的代码可以正常工作,因为数组引用的作用是跟踪,而不是内部对象的引用。您可以根据需要将newState[1]散布到一个新对象中,但是您需要从状态数组中删除较旧的对象。

干杯!

答案 1 :(得分:0)

您只需要将克隆的,修改后的对象与其余prevComponents一起返回。目前,您仅返回旧状态,因此不会发生任何变化(除了您意外返回的是对象,而不是数组之外的事实)。

编辑:现在看起来不太漂亮,但是很安全。

function onActivateHandler(){
    setComponents((prevComponents) => {
      const copy = [...s];
      const newState = {...copy.splice(1, 1)[0]}
      newState.active = true;
      return [...copy, newState];
    })
 }