如何使用 useState 更新初始状态对象的特定 属性
How to update a specific property of an initial state object using useState
考虑一下我需要在获取一些数据后更新状态的代码,我只需要更新初始状态的数据部分 (clientData):
const [clientData, setClientData] = useState({
data: {},
product: 'profile'
});
useEffect(() => {
getProducts(1).then(res =>
setClientData({ ...clientData, data: res.data })
);
}, []);
我怎样才能并且是否有可能只更新初始状态的 "data" 部分而不必传播它 (...clientData
)
这是不可能的,因为从 useState
挂钩 replaces the prior state value 返回的 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 是一个很棒的库,您可以了解更多关于它的信息here
这对于 useState 是不可能的。不过 useReducer 是可能的。
如前所述,最佳做法是在多个挂钩之间拆分此状态,但是,实际上可以使用 useState()
使用这样的函数来做到这一点:
const setClientDataSelectively = ({data=null, product=null}) => {
setClientData((prevState) => ({
data: data !== null ? data : data,
product: product !== null ? product : product,
}));
}
参数默认为null,然后使用prevState对象和一个conditional operator,你可以检查是否有东西实际上是传入并相应地属性。
考虑一下我需要在获取一些数据后更新状态的代码,我只需要更新初始状态的数据部分 (clientData):
const [clientData, setClientData] = useState({
data: {},
product: 'profile'
});
useEffect(() => {
getProducts(1).then(res =>
setClientData({ ...clientData, data: res.data })
);
}, []);
我怎样才能并且是否有可能只更新初始状态的 "data" 部分而不必传播它 (...clientData
)
这是不可能的,因为从 useState
挂钩 replaces the prior state value 返回的 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 是一个很棒的库,您可以了解更多关于它的信息here
这对于 useState 是不可能的。不过 useReducer 是可能的。
如前所述,最佳做法是在多个挂钩之间拆分此状态,但是,实际上可以使用 useState()
使用这样的函数来做到这一点:
const setClientDataSelectively = ({data=null, product=null}) => {
setClientData((prevState) => ({
data: data !== null ? data : data,
product: product !== null ? product : product,
}));
}
参数默认为null,然后使用prevState对象和一个conditional operator,你可以检查是否有东西实际上是传入并相应地属性。