如何在全局作用域立即设置状态并解决Select组件状态延迟更新问题
问题描述
我有一个Select组件(下拉菜单),选择选项时id并未立即更新,仍保留前一个选中项的id,只有重新选择时id才会更新。另外我有三个Select组件,每个都需要调用handleRecalculateReservationAmount(selectedVehicleId, selectedServiceId, vehicleBodyId)方法,想知道如何提取e.value并让它在多个组件中可用。
相关代码示例:
const EditBookingDetailsModal = () => { const { modals, toggleModal, T } = useUI() const { laundry } = useLaundryContext() const { currentReservation, handleRecalculateReservationAmount, setState} = useReservationsContext() const { vehicleBodyTypeId } = currentReservation as IReservationDetails const bodyTypes: ICarBodyType[] = laundry?.bodyTypes || [] const [vehicleBodyId, setVehicleBodyId] = useState(vehicleBodyTypeId) const generateBodyTypesOptions = () => bodyTypes.map((bodyType) => ({ label: bodyType.name, value: bodyType.id })) return ( <Modal isOpen={modals.editReservationDetailsModal.isOpened} onClose={() => { toggleModal("editReservationDetailsModal", false) setState({ modifiedPrice: null }) }} title={T("booking.details.edit.modal.title")} styles={{ headerPadding: "20px 15px 20px 23px", width: "566px", bodyPadding: "0px 0px 0px 0px", }} > <Box paddingBottom="40px"> <Flex gap="30px" padding="14px 23px 20px 23px" borderBottom="1px solid #E9F2FD " > <FormControl width="55%"> <FormLabel id="auto" text={T("booking.details.edit.auto")} /> <Select value={vehicleBodyId|| ""} onChange={(e: any) => { setVehicleBodyId(e.value) handleRecalculateReservationAmount(selectedVehicleId, selectedServiceId, vehicleBodyId) }} options={generateBodyTypesOptions()} inputStyles={{ height: "60px", }} // placeholderStyles={{ fontSize: "var(--chakra-fontSizes-m)" }} /> </FormControl> </Flex> </Box> </Modal> ) }
解决方案
1. 修复id不立即更新的问题
React的useState更新是异步的,调用setVehicleBodyId(e.value)后,vehicleBodyId不会立刻变成新值,直接用它传参只会拿到旧值。有两种解决方式:
- 直接用
e.value作为参数传入计算方法:onChange={(e: any) => { setVehicleBodyId(e.value) handleRecalculateReservationAmount(selectedVehicleId, selectedServiceId, e.value) }} - 用
useEffect监听vehicleBodyId变化,触发计算:useEffect(() => { if (vehicleBodyId) { handleRecalculateReservationAmount(selectedVehicleId, selectedServiceId, vehicleBodyId) } }, [vehicleBodyId, selectedVehicleId, selectedServiceId, handleRecalculateReservationAmount]) // onChange仅负责更新状态 onChange={(e: any) => { setVehicleBodyId(e.value) }}
2. 提取共享逻辑给多个Select组件
针对三个Select组件的复用需求,可以合并状态并编写通用处理函数:
步骤1:合并选中状态
把三个Select的选中值统一存到一个state对象中:
const [selectedValues, setSelectedValues] = useState({ vehicleId: currentReservation?.vehicleId || "", serviceId: currentReservation?.serviceId || "", bodyTypeId: currentReservation?.vehicleBodyTypeId || "" })
步骤2:编写通用change处理函数
const handleSelectChange = (field: 'vehicleId' | 'serviceId' | 'bodyTypeId', e: any) => { const newValues = { ...selectedValues, [field]: e.value } setSelectedValues(newValues) // 直接用最新值调用计算方法 handleRecalculateReservationAmount(newValues.vehicleId, newValues.serviceId, newValues.bodyTypeId) }
步骤3:给每个Select绑定处理函数
以车辆类型Select为例:
<Select value={selectedValues.bodyTypeId || ""} onChange={(e) => handleSelectChange('bodyTypeId', e)} options={generateBodyTypesOptions()} // 其他属性... />
另外两个Select组件只需修改对应的field参数即可复用该函数,同时保证每次选择都能传入最新的选中值。
内容的提问来源于stack exchange,提问作者Nika
相关产品推荐
相关产品推荐

