react-select多步表单切换步骤时多选下拉框默认值设置方法
问题根源
三个核心错误导致回显失效:
- 子组件
CreateFormFirstStep的props接收语法错误:函数组件仅第一个参数为传入的props对象,你把selectedValue写在了第二个参数位置,实际拿到的永远是undefined,根本读不到父组件存储的选中值 - 父子组件传值的prop名不匹配:父组件传递选中值时用的prop名是
optionSelected,子组件读取时用的是selectedValue,两边名称对不上 - react-select受控用法不符合官方要求:组件不识别
defaultValue(仅非受控模式首次生效)、自定义selectedValue属性做值绑定,必须用官方指定的valueprop传值,且传入值必须和options格式一致,也就是{value: 任意类型, label: 字符串}结构的对象/对象数组,不能直接传存储的原始value值 - 初始状态类型不匹配:多选场景下
car字段初始值设为空字符串,和后续存储的数组类型不一致,容易引发判断异常
修复方案
按以下顺序调整代码即可:
- 修正子组件props解构语法,所有接收的属性统一放在第一个参数的解构对象中
- 统一父子组件传值的prop名称,避免拼写/命名不一致
- 移除Select组件上无效的
defaultValue、自定义selectedValue属性,改用valueprop做受控绑定,回显时把存储的原始value数组映射为和options格式一致的选项对象数组 - 把初始状态中
car字段的空字符串改为空数组,匹配多选场景的数组类型
修正后代码
CreateForm.js
// CreateForm.js function CreateForm() { const [selectedValue, setSelectedValue] = useState({ profile_name: "", car: [], // 多选场景初始值设为空数组,统一类型 }); const [step, setStep] = useState(1); const nextStep = () => { if (step < 2) { setStep(step + 1); } else if (step === 2) { console.log(selectedValue); } }; const prevStep = () => { if (step > 1) { setStep(step - 1); } }; const handleChange = (name) => (e) => { setSelectedValue((prevState) => ({ ...prevState, [name]: Array.isArray(e) ? e.map((x) => x.value) : [], })); }; return ( <div className="bg-dark vh-100 text-light"> <div className="d-flex flex-column justify-content-center"> <div> { { 1: ( <CreateFormFirstStep handleChange={handleChange} selectedValue={selectedValue} // 统一prop名,和子组件接收字段一致 /> ), 2: ( <CreateFormSecondStep handleChange={handleChange} /> ), }[step] } </div> </div> <div className="d-flex flex-row justify-content-around px-5 mt-5"> {step > 1 ? ( <button className="btn btn-secondary" onClick={prevStep}> Back </button> ) : null} <button className="btn btn-primary" onClick={nextStep}> {step === 2 ? "Save" : "Next"} </button> </div> </div> ); } export default CreateForm;
CreateFormFirstStep.jsx
// CreateFormFirstStep // 修正props解构,所有属性放在第一个参数的解构对象中 const CreateFormFirstStep = ({ handleChange, selectedValue }) => { const data = [ { value: 'bugatti', label: 'Bugatti' }, { value: 'ferrari', label: 'Ferrari' }, { value: 'am', label: 'Aston Martin' }, { value: 'koenigsegg', label: 'Koenigsegg' }, { value: 'bmw', label: 'BMW' }, { value: 'cadillac', label: 'Cadillac' }, ]; // 将存储的value数组映射为react-select要求的选项格式,用于受控回显 const selectedCarOptions = data.filter(option => selectedValue.car.includes(option.value)); return ( <div className="CreateFormFirstStep"> <h3>Test name</h3> <Select className="text-dark" style={{ display: "flex", flexDirection: "column" }} placeholder="Choose..." options={data} isMulti closeMenuOnSelect={false} hideSelectedOptions={false} isLoading={!data} onChange={handleChange("car")} value={selectedCarOptions} // 用官方指定的value属性做受控绑定 name={"car"} /> </div> ); }; export default CreateFormFirstStep;
调整完成后,切换表单步骤时父组件的状态不会丢失,切回第一步时Select组件会自动读取value属性传入的已选选项,完成值的预填充。
内容的提问来源于stack exchange,提问作者m-derra
相关产品推荐
相关产品推荐

