ReactJS TypeScript中react-select多选无法添加onChange属性的问题
React-Select多选下拉框TypeScript类型错误解决
问题说明
在React中使用react-select实现多选下拉框时,添加onChange属性触发TypeScript类型错误,提示只读类型MultiValue<Vehicle>无法赋值给可变类型Vehicle[],具体错误信息如下:
ERROR in src/components/Pages/CreatePage.tsx:196:25 TS2322: Type '(selected: Vehicle[] | null) => void' is not assignable to type '(newValue: MultiValue<Vehicle>, actionMeta: ActionMeta<Vehicle>) => void'. Types of parameters 'selected' and 'newValue' are incompatible. The type 'MultiValue<Vehicle>' is 'readonly' and cannot be assigned to the mutable type 'Vehicle[]'. 194 | isClearable={true} 195 | backspaceRemovesValue={true} > 196 | onChange={handleSelectChange} | ^^^^^^^^ 197 | 198 | />
问题原因
当react-select开启isMulti模式时,onChange回调的第一个参数类型是MultiValue<Vehicle>,它本质是只读数组类型,而我们定义的handleSelectChange函数参数为可变的Vehicle[],TypeScript的严格类型检查会判定二者不兼容,因此抛出错误。
解决方案
方法1:适配参数类型为只读数组
直接修改handleSelectChange的参数类型,匹配react-select的要求:
const handleSelectChange = (selected: readonly Vehicle[]) => { setVehicles([...selected]); // 用扩展运算符转为可变数组 };
或者导入react-select内置的MultiValue类型来定义参数:
import Select, { MultiValue, ActionMeta } from 'react-select'; // ... const handleSelectChange = (selected: MultiValue<Vehicle>, actionMeta: ActionMeta<Vehicle>) => { setVehicles([...selected]); };
方法2:将只读数组转为可变数组
如果不想修改参数类型,可以在函数内部把只读数组转为可变数组后再更新状态:
const handleSelectChange = (selected: readonly Vehicle[] | null) => { if (selected) { setVehicles(Array.from(selected)); // 用Array.from转换 // 或者使用扩展运算符:setVehicles([...selected]); } else { setVehicles([]); } };
方法3:将状态类型改为只读数组
如果业务中不需要修改状态数组的内容,可以直接把useState的类型改为只读数组:
const [vehicles, setVehicles] = useState<readonly Vehicle[]>([]); const handleSelectChange = (selected: readonly Vehicle[]) => { setVehicles(selected); };
修正后的完整代码
import React, { useState } from 'react'; import Select, { MultiValue } from 'react-select'; interface Vehicle { id: number; make: string; model: string; year: number; } const vehicles: Vehicle[] = [ { id: 1, make: 'Ford', model: 'Fiesta', year: 2003 }, { id: 7, make: 'Audi', model: 'A4', year: 2009 }, ]; const YourComponent: React.FC = () => { const [selectedVehicles, setSelectedVehicles] = useState<Vehicle[]>([]); const handleSelectChange = (selected: MultiValue<Vehicle>) => { setSelectedVehicles([...selected]); }; return ( <Select isMulti getOptionLabel={(vehicle: Vehicle) => vehicle.model} getOptionValue={(vehicle: Vehicle) => vehicle.model} options={vehicles} isClearable={true} backspaceRemovesValue={true} onChange={handleSelectChange} /> ); }; export default YourComponent;
内容的提问来源于stack exchange,提问作者Prasath S
相关产品推荐
相关产品推荐

