React钩子替换旧状态

时间:2019-10-28 08:38:28

标签: reactjs

我正在学习有关React钩子的知识,我正在通过academind中的示例进行浏览,

作者在那里提到过类似的事情

  

当您使用React Hooks设置新状态(即在我们的示例中通过setCart)时,旧状态将始终被替换!

可能带有以下示例:

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,它也会替换旧状态,因此作者在这里试图表示什么?

在本文的后面,类似这样

  

如果它是一个对象,请记住,React在设置时不会将您的旧状态与新状态合并。您将始终覆盖旧状态,因此可能需要您进行任何合并!

这听起来与我们在类baed组件中所做的setState非常相似

2 个答案:

答案 0 :(得分:6)

调用setState()时,React将您提供的对象合并为当前状态。

随着useState更新,状态变量总是替换它而不是合并它。

我将尝试用一个样本来解释:

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

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

在这里,在setState之后,姓氏不会丢失其值(因为setState合并了),所以状态看起来像这样:

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

但是如果我们使用钩子来做到这一点:

setUser({
  name: "Bill"
})

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

{
  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>
  );
}

代码和框:

Python

答案 1 :(得分:0)

  

如果它是一个对象,请记住,React在设置时不会将您的旧状态与新状态合并。您将始终覆盖旧状态,因此可能需要您进行任何合并!

他的意思是,当您使用对象初始化状态时

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

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

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

setCart([...cart, newCartArray])

setCart({...cart, newCartObject})

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