react-select 在改变 api 数据时更新值
react-select update value when mutating api data
我有一个 react-select 组件,我在其中提交来自 api 数据的选项,每当我编辑来自 api 的人名时,选项中的名称更改但值上的名称保持不变。
我想在更改人名后更改 select 的值。
--这里我使用react-query更新一个人的名字
const deliveryPersonUpdate = (values) => {
const id = deliveryBoy && deliveryBoy.id;
const params = { deliveryBoyId: id, ...values };
updateDeliveryPerson.mutate(params, {
onSuccess: (data) => {
toggle();
setDeliveryBoy(data?.delivery_boy);
queryClient.invalidateQueries([GET_DELIVERY_BOY_LIST.name]);
toast.success("Category Updated");
},
onError: (error) => {
showErrorMessages({ error });
},
});
};
const handleSubmit = (values) => {
deliveryPersonUpdate(values);
};
--select分量
<Select
onChange={(obj) => handleChange(obj)}
paintBg
noOptionsMessage={noOptionsMessage}
name="deliveryBoySelect"
className={cx(styles.addDeliveryBoySelect)}
defaultValue={
!isEmpty(data?.delivery_boys) && {
label: data?.delivery_boys?.[0].name,
value: data?.delivery_boys?.[0].id,
}
}
options={data?.delivery_boys.map((d) => ({
label: d.name,
value: d.id,
}))}
isSearchable
/>
--处理 select
的变化
const handleChange = (e) => {
const deliveryBoyData = data.delivery_boys.find(
(obj) => obj.id === e.value
);
setDeliveryBoy(deliveryBoyData);
};
--此处,更改人名后,选项会立即更新,但值不会更新
您面临的问题是您对 select 使用 defaultValue
,这意味着 select 是 不受控制的 。任何时候 defaultValue
被更改,select 不会对此更改做出反应,因为它不应该,它只是默认值。
您有两个选择:
- 使select受控(通过使用状态)
- 使select键控(当默认值改变时re-mounting它)
至于受控select
您必须将 defaultValue
替换为 value
,但还要附加一个更改状态的 onChange
处理程序。您已经有了 onChange
,因为它更新了 RQ 中的状态,但是由于您使用的是 defaultValue
,它不会传播回来。但是,如果你只是使用 value
我认为会有闪烁,因为 RQ 本质上是异步的,所以用户可以看到一个帧,其中的值仍然不同步。因此,为了完全做到这一点,您还必须引入同步状态。
const [value, setValue] = useState(props.value)
const onChange = (e) => {
setValue(e.target.value)
props.onChange(e.target.value)
}
useEffect(() => {
setValue(props.value)
}, [props.value])
<select value={value} onChange={onChange} />
这是做什么的,它使用 setState
保持本地状态,使用 useEffect
处理来自 props 的更新,并因此使用 value
而不是 defaultValue
。如有必要,您也可以提升状态。
至于键控组件
如果之前的解决方案不符合人体工程学或出于任何原因不好并且组件是 small-ish,您还可以决定不保留本地状态,而是卸载组件并安装一个新鲜实例。结果是,当值更改时,它会安装一个新组件,以便可以再次使用 defaultValue
。除了添加 key
属性外,您保持 select 不变。
<select key={props.value} defaultValue={props.value} onChange={onChange}>
键与值相同意味着它们将同步。当本地值改变时,它不会闪烁,因为我们没有设置value
,DOM是自己更新的,而当props.value
最终改变是通过RQ异步方式,它重新创建组件,使用当前 defaultValue
.
我有一个 react-select 组件,我在其中提交来自 api 数据的选项,每当我编辑来自 api 的人名时,选项中的名称更改但值上的名称保持不变。
我想在更改人名后更改 select 的值。
--这里我使用react-query更新一个人的名字
const deliveryPersonUpdate = (values) => {
const id = deliveryBoy && deliveryBoy.id;
const params = { deliveryBoyId: id, ...values };
updateDeliveryPerson.mutate(params, {
onSuccess: (data) => {
toggle();
setDeliveryBoy(data?.delivery_boy);
queryClient.invalidateQueries([GET_DELIVERY_BOY_LIST.name]);
toast.success("Category Updated");
},
onError: (error) => {
showErrorMessages({ error });
},
});
};
const handleSubmit = (values) => {
deliveryPersonUpdate(values);
};
--select分量
<Select
onChange={(obj) => handleChange(obj)}
paintBg
noOptionsMessage={noOptionsMessage}
name="deliveryBoySelect"
className={cx(styles.addDeliveryBoySelect)}
defaultValue={
!isEmpty(data?.delivery_boys) && {
label: data?.delivery_boys?.[0].name,
value: data?.delivery_boys?.[0].id,
}
}
options={data?.delivery_boys.map((d) => ({
label: d.name,
value: d.id,
}))}
isSearchable
/>
--处理 select
的变化const handleChange = (e) => {
const deliveryBoyData = data.delivery_boys.find(
(obj) => obj.id === e.value
);
setDeliveryBoy(deliveryBoyData);
};
--此处,更改人名后,选项会立即更新,但值不会更新
您面临的问题是您对 select 使用 defaultValue
,这意味着 select 是 不受控制的 。任何时候 defaultValue
被更改,select 不会对此更改做出反应,因为它不应该,它只是默认值。
您有两个选择:
- 使select受控(通过使用状态)
- 使select键控(当默认值改变时re-mounting它)
至于受控select
您必须将 defaultValue
替换为 value
,但还要附加一个更改状态的 onChange
处理程序。您已经有了 onChange
,因为它更新了 RQ 中的状态,但是由于您使用的是 defaultValue
,它不会传播回来。但是,如果你只是使用 value
我认为会有闪烁,因为 RQ 本质上是异步的,所以用户可以看到一个帧,其中的值仍然不同步。因此,为了完全做到这一点,您还必须引入同步状态。
const [value, setValue] = useState(props.value)
const onChange = (e) => {
setValue(e.target.value)
props.onChange(e.target.value)
}
useEffect(() => {
setValue(props.value)
}, [props.value])
<select value={value} onChange={onChange} />
这是做什么的,它使用 setState
保持本地状态,使用 useEffect
处理来自 props 的更新,并因此使用 value
而不是 defaultValue
。如有必要,您也可以提升状态。
至于键控组件
如果之前的解决方案不符合人体工程学或出于任何原因不好并且组件是 small-ish,您还可以决定不保留本地状态,而是卸载组件并安装一个新鲜实例。结果是,当值更改时,它会安装一个新组件,以便可以再次使用 defaultValue
。除了添加 key
属性外,您保持 select 不变。
<select key={props.value} defaultValue={props.value} onChange={onChange}>
键与值相同意味着它们将同步。当本地值改变时,它不会闪烁,因为我们没有设置value
,DOM是自己更新的,而当props.value
最终改变是通过RQ异步方式,它重新创建组件,使用当前 defaultValue
.