React自定义SelectField组件Subject选项不自动加selected属性怎么解决
问题原因
- 核心原因是React的
defaultValue属性仅会在组件首次挂载渲染时生效1次,后续组件props/state更新不会重新计算defaultValue的匹配逻辑。 return (<CountrySelectField>正常运行是因为它的options是静态数据,<SelectField>首次渲染时所有option已经存在,`defaultValue`可以正确匹配到对应选项。 )return (<SubjectSelectField>的subject数据是异步请求获取的:<SelectField>首次渲染时subjects是空数组,<select>下只有默认的`None`选项,此时`defaultValue`匹配不到目标值,等接口返回数据更新subjects后,<select>已经完成首次渲染,不会再重新处理`defaultValue`,因此无法自动选中。 )- 后续将Subject改为函数式组件并把JSX存入state的操作属于错误用法:state不应该存储渲染后的JSX元素,应该存储原始数据,在渲染阶段再转换为UI组件。
解决方案
1. 修正SubjectSelectField的state存储逻辑
state只存储接口返回的原始数据,新增加载状态,等数据加载完成后再渲染
export function SubjectSelectField(props) { const [subjects, setSubjects] = useState([]); const [loading, setLoading] = useState(true); useEffect(() => { const getSubjects = async () => { let reqObj = new RequestHandler("/courses/subjects/"); const data = await reqObj.sendRequest(); setSubjects(data); setLoading(false); }; getSubjects(); }, []); if (loading) return null; return <SelectField options={subjects} {...props} />; }
2. 调整SelectField的option生成逻辑
统一处理数组类型的options,不需要依赖Subject类的to_option方法,适配不同数据源结构:
const generate_options = () => { let element_list = []; element_list.push( <SelectOption key={0} option_value="" option_text="None" /> ); if (!Array.isArray(props.options)) { let count = 1; for (var [value, name] of Object.entries(props.options)) { element_list.push( <SelectOption key={count} option_value={value} option_text={name} /> ); count += 1; } } else { props.options.forEach((item, index) => { element_list.push( <SelectOption key={index+1} option_value={`${item.id ?? Object.keys(item)[0]}`} option_text={item.name ?? Object.values(item)[0]} /> ); }); } return element_list; };
如果需要更高的通用性,可以给SelectField新增valueField、labelField两个自定义props,灵活指定取option值和显示文本的字段。
可选优化:改为受控组件适配所有场景
如果不想加加载状态,可以把
相关产品推荐
相关产品推荐

