【问题标题】:How to update a specific property of an initial state object using useState如何使用 useState 更新初始状态对象的特定属性
【发布时间】:2019-12-31 04:32:05
【问题描述】:

考虑在获取一些数据后我需要更新状态的代码,我只需要更新初始状态的数据部分(clientData):

 const [clientData, setClientData] = useState({
    data: {},
    product: 'profile'
 });

 useEffect(() => {
    getProducts(1).then(res =>
      setClientData({ ...clientData, data: res.data })
    );
  }, []);

我怎样才能以及是否可以只更新初始状态的“数据”部分而不必传播它 (...clientData)

【问题讨论】:

  • 我认为这不可能。您要么必须使用 object spread 要么 Object.assign
  • 另一种选择是用多个钩子分割你的状态
  • 是的,我想到了,使用钩子时它被认为是最佳实践吗?所以你会有const [data, setData] = useState({data:}) and const [product, setProduct] = useState({product:'profile'})

标签: reactjs react-hooks use-effect


【解决方案1】:

这是不可能的,看到 set 方法从 useState 钩子 replaces the prior state value 返回,无论你传递什么,都是完整的。

一种可能性是用多个钩子分隔您的状态,这将为您提供更新组件状态的更细粒度的方法:

/* Separate your state across multiple hooks */
const [data, setData] = useState({});
const [product, setProduct] = useState('profile');

useEffect(() => {
    getProducts(1).then(res =>
      /* Only update data portion of state via setData hook */
      setData(res.data)
    );
 }, []);

【讨论】:

  • 我会将其标记为正确答案,因为它似乎被认为是最佳实践!
【解决方案2】:

这里有几个选项...

1) 分开以下...

const [clientData, setClientData] = useState({
    data: {},
    product: 'profile'
 });

进入...

const [clientData, setClientData] = useState({});
const [clientProduct, setClientProduct] = useState('profile');

然后您可以更新您需要的数据部分。在您上面列出的情况下,这可能是推荐的。或者……

2) 使用像 'immer' 这样的库,它允许您通过简单地修改现有的状态树来创建新的状态树...

import produce from 'immer';

...

const [clientData, setClientData] = useState({
  data: {},
  product: 'profile'
});

useEffect(() => {
  getProducts(1).then(res =>
    setClientData(produce(clientData, draft => {
      draft.data = res.data;
    }));
  );
}, []);

Immer 是一个很棒的库,您可以了解更多关于它的信息here

【讨论】:

    【解决方案3】:

    这对于 useState 是不可能的。不过,useReducer 是可能的。

    【讨论】:

      【解决方案4】:

      如前所述,最佳做法是在多个钩子之间拆分此状态,但是,实际上可以使用以下函数通过 useState() 执行此操作:

      const setClientDataSelectively = ({data=null, product=null}) => {
          setClientData((prevState) => ({
              data: data !== null ? data : data,
              product: product !== null ? product : product,
          }));
      }
      

      参数默认为 null,然后使用 prevState 对象和conditional operator,您可以检查是否确实传入了某些内容并进行相应的属性。 p>

      【讨论】:

        猜你喜欢
        • 2020-03-29
        • 1970-01-01
        • 2020-07-16
        • 2021-10-02
        • 2021-09-22
        • 2021-12-14
        • 1970-01-01
        相关资源
        最近更新 更多