开发者问题收集

React hook 替换旧状态

2019-10-28
4890

我正在学习 React Hooks,并且正在学习 academind 中的示例,

作者在那里提到了类似这样的内容

When you set a new state with React Hooks (i.e. via setCart in our example), the old state will always be replaced!

可能还有以下示例:

import React, { useState } from 'react'

const Shop = props => {
  const [cart, setCart] = useState([])
  const cartHandler = () => {
    setCart(['A Book'])
  }
  return <button onClick={cartHandler}>Add to Cart</button>
}

我无法理解这一点。

在具有状态的类中,如果我们执行 setState,它也会替换旧状态,那么作者在这里试图表达什么意思?

在本文后面,还有类似这样的内容

If it is an object, just keep in mind that React won’t merge your old state with your new state when you’re setting it. You will always overwrite the old state and hence any merging that might be required has to be done by you!

这听起来与我们在基于类的组件中执行的 setState 非常相似

2个回答

当你调用 setState() 时,React 会将你提供的对象合并到当前状态中。

使用 useState 更新状态变量始终会替换它而不是合并它。

我会尝试用一个示例来解释:

state = {
    name: "Michael",
    surname: "Jackson"
}

this.setState({
    name: "Bill"
})

在这里,在 setState 之后,surname 并没有丢失其值(因为 setState 合并了)所以状态将如下所示:

{
   name: "Bill",
   surname: "Jackson"
}

但如果我们使用 hooks 来执行此操作:

setUser({
  name: "Bill"
})

surname 丢失了,所以状态是这样的:

{
  name: "Bill"
}

为了保留姓氏,我们可以使用扩展运算符复制旧状态。

setUser({
  ...user,
  name: "Bill"
});

完整的例如:

function App() {
  const initialState = { name: "Michael", surname: "Jackson" };

  const [user, setUser] = useState(initialState);

  const handleClickWrong = () => {
    setUser({
      name: "Bill"
    });
  };

  const handleClickCorrect = () => {
    setUser({
      ...user,
      name: "Bill"
    });
  };

  const handleClickReset = () => {
    setUser(initialState);
  };

  return (
    <div className="App">
      <button onClick={handleClickWrong}>Change name (wrong)</button>
      <button onClick={handleClickCorrect}>Change name (correct)</button>
      <button onClick={handleClickReset}>Change name (reset state)</button>
      <hr />
      {JSON.stringify(user)}
    </div>
  );
}

Codesandbox:

https://codesandbox.io/s/hook-not-merging-state-cqj2g

SuleymanSah
2019-10-28

If it is an object, just keep in mind that React won’t merge your old state with your new state when you’re setting it. You will always overwrite the old state and hence any merging that might be required has to be done by you!

这句话的意思是,当你用一个对象初始化状态时

const [cart, setCart] = useState([])

const [cart, setCart] = useState({})

当 setState 时你想将新状态添加到旧状态中,你必须覆盖旧状态。你可以使用 es6 Destructuring_assignment

setCart([...cart, newCartArray])

setCart({...cart, newCartObject})

如果你不这样做,你的新状态将被替换而不是覆盖,并且你将丢失旧状态。

Hải Bùi
2019-10-28