引起钩子对象更新的最佳方法

时间:2019-07-31 19:43:12

标签: javascript reactjs react-hooks

说我有一个像这样的功能组件:

function App(){

  const [obj, setObj] = useState({arr:[1,2,3,4,5]})

  const swap = (a,b)=>{
    const updatedArr = Object.assign(
      obj.arr,
      {
        [a.toString()]:obj.arr[b],
        [b.toString()]:obj.arr[a]
      }
    )
    setObj(
      Object.assign(
        obj,
        {arr:updatedArr}
      )
    )
  };

  const buttonAction = (e) => {
    e.preventDefault();
    swap(0,4)
  }

  return <div>
    <button onClick = {buttonAction}>swap</button>
    <ul>
    {
      obj.arr.map(
        item=>{return <li key={item.toString()}>{item}</li>}
        )
    }
    </ul>
  </div>
}

“交换”按钮使swap函数交换数组的第一个和最后一个元素。当我在开发人员工具中检查此情况时,实际上就是这样:

在功能之前: object before function

后函数: object after function

但是,它不会导致重新呈现,因此列表在视图中保持不变。

我可以通过更改交换功能以包含以下内容来强制重新渲染:

const newObj = Object.assign(
    obj,
    {arr:updatedArr}
  )
setObj(
  Object.assign(
    {},
    newObj
  )
)

因此,通过将更新的对象分配给新对象,我可以强制重新渲染。这是最好的方法吗?还是有更好的方法让挂钩中的对象发生更改时重新渲染组件?

更新:在有人问我“更好”是什么意思之前,我的意思是更“反应准确”,这与设计框架的人员的意图一致,他们肯定已经预见到了情况像这样。

1 个答案:

答案 0 :(得分:2)

您似乎正在直接修改状态,这导致更新不会触发渲染。

setObj(
    Object.assign(
        obj,
        {arr:updatedArr}
    )
)

Object.assign使用新的有序arr直接更改obj变量(您的状态)。然后setObj正在获取此obj并将其分配给自身-此时,react正在比较对象(与Object.is)以确定是否需要渲染。由于它是完全相同的对象,因此不会重新渲染。

在您的工作更新中,您正在分配一个新对象,因此react将呈现。

也就是说,反应的方法是不直接修改状态(本质上就是稍加修改即可完成的操作)

const swap = (a,b)=>{
    const updatedArr = Object.assign(
        [...obj.arr],
        {
            [a.toString()]:obj.arr[b],
            [b.toString()]:obj.arr[a]
        }
    )
    setObj(
        Object.assign(
            {},
            obj,
            {arr:updatedArr}
        )
    )
};