考虑在获取某些数据后我需要更新状态的代码,我只需要更新初始状态的数据部分(clientData):
const [clientData, setClientData] = useState({
data: {},
product: 'profile'
});
useEffect(() => {
getProducts(1).then(res =>
setClientData({ ...clientData, data: res.data })
);
}, []);
我如何以及是否可以只更新初始状态的"数据"部分而不必传播它(...clientData
)
这是不可能的,因为从useState
钩返回的 set 方法将先前的状态值替换为您传递它的任何值,因为它是完整的。
一种可能性是用多个钩子分离你的状态,这将为你提供一种更精细的方法来更新组件的状态:
/* 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)
);
}, []);
这里有几个选项...
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是一个很棒的图书馆,你可以在这里了解更多关于它的信息
这对于 useState 是不可能的。不过,使用useReducer是可能的。
如前所述,最佳做法是在多个钩子之间拆分此状态,但是,实际上可以使用如下函数通过useState()
来执行此操作:
const setClientDataSelectively = ({data=null, product=null}) => {
setClientData((prevState) => ({
data: data !== null ? data : data,
product: product !== null ? product : product,
}));
}
参数默认为null,然后使用prevState对象和条件运算符,您可以检查是否实际传入了某些内容并相应地进行属性。