ReactJS编辑Survey表单时Select下拉选择器偶发无法正常选中赋值问题
问题根因
- 竞态条件:拉取survey详情、拉取元数据两个异步请求返回顺序不固定,
_setProperValForMetaDataSelect方法执行时经常出现其中一类数据未加载完成的情况,导致匹配不到对应值
- 竞态条件:拉取survey详情、拉取元数据两个异步请求返回顺序不固定,
- 入口判断逻辑完全失效:
this.state.surveyMeta是对象,不存在length属性,原判断this.state.surveyMeta.length == 0永远为false,无法拦截数据未加载完成的执行场景
- 入口判断逻辑完全失效:
- 值匹配逻辑写反:元数据结构为
{数字key: 文本value},需求是根据接口返回的文本值找对应数字key,但代码中判断条件写为if (key == survey_type),导致大部分场景匹配不到值,返回空字符串覆盖原有值
- 值匹配逻辑写反:元数据结构为
- Select组件属性错误:Formik是受控组件模式,代码中用了只在首次渲染生效的
defaultValue,后续state更新后Select不会跟着响应,就会显示默认的--select--
- Select组件属性错误:Formik是受控组件模式,代码中用了只在首次渲染生效的
修复方案
1. 修正转换方法的入口判断与匹配逻辑
_setProperValForMetaDataSelect() { // 必须同时满足survey加载完成、元数据加载完成才执行转换 if (this.props.isSurveyLoading || this.state.surveyMeta.survey_types.length === 0) { return } const { survey_types, survey_subtypes, transit_types, currencies, live_survey_types } = this.state.surveyMeta const { currency, survey_type, survey_subtype, transit_type, live_survey_type } = this.state.survey || {} let _currency = '' let _survey_type = '' let _survey_subtype = '' let _transit_type = '' let _live_survey_type = '' // 修正匹配逻辑:用返回的文本值匹配元数据的value,取对应数字key currencies.forEach((item) => { for (const [key, value] of Object.entries(item)) { if (value == currency) { _currency = key } } }) survey_types.forEach((item) => { for (const [key, value] of Object.entries(item)) { if (value == survey_type) { _survey_type = key } } }) transit_types.forEach((item) => { for (const [key, value] of Object.entries(item)) { if (value == transit_type) { _transit_type = key } } }) survey_subtypes.forEach((item) => { for (const [key, value] of Object.entries(item)) { if (value == survey_subtype) { _survey_subtype = key } } }) live_survey_types.forEach((item) => { for (const [key, value] of Object.entries(item)) { if (value == live_survey_type) { _live_survey_type = key } } }) let updatedValues = { currency: _currency || currency, survey_type: _survey_type || survey_type, survey_subtype: _survey_subtype || survey_subtype, transit_type: _transit_type || transit_type, live_survey_type: _live_survey_type || live_survey_type } this.setState({ survey: { ...this.state.survey, ...updatedValues } }) }
2. 修正Select组件属性,适配受控模式
把_generateSelectElement方法中的defaultValue替换为value,绑定Formik的对应字段值:
_generateSelectElement(name, onChange, onBlur, options, selectedValue = null) { return <Input name={name} type='select' onBlur={onBlur} onChange={onChange} value={selectedValue || ''} // 替换原defaultValue > <option value="">--Select--</option> {options ? options.map((item) => { for (const [key, value] of Object.entries(item)) { return <option key={value} value={key}>{value}</option> // 同时修正value和显示文本的对应关系 } }) : null} </Input> }
3. 优化异步加载逻辑避免竞态
可以新增两个状态标记isMetaLoaded和isSurveyLoaded,只有两个标记都为true的时候才调用一次_setProperValForMetaDataSelect,避免多次无效调用覆盖正确值。
内容的提问来源于stack exchange,提问作者Ropali Munshi
相关产品推荐
相关产品推荐

