如何删除数组冗余行并避免报错:Cannot read properties of undefined (reading 'label')
问题分析与解决办法
先说说你遇到的两个错误原因
1. 「Cannot read properties of undefined (reading 'label')」
第二个for循环是照着options的长度(2次)遍历的,但删完冗余元素后optionsThree只剩1个元素,循环到第2次时optionsThree[1]不存在,访问option3.label自然就报错了。
2. 「Encountered two children with the same key」
两个循环都用i作为组件的key,第一个循环生成key=0、1,第二个循环也生成0、1,React要求列表子元素的key必须唯一,这不就冲突了嘛。
修复错误的基础版代码
先把循环逻辑和key的问题解决,同时加存在判断避免取undefined:
const rows: JSX.Element[] = []; // 处理前两行的左右Radio for (let i = 0; i < options.length; i += 1) { const option1 = options[i]; const option2 = optionsTwo[i]; rows.push( <View key={`pair-${i}`}> <View style={{ flexDirection: "row" }}> {/* 加存在判断,避免意外报错 */} {option1 && ( <Radio onPress={() => onChange(option1.value)} label={option1.label} checked={option1.value === value} style={{ flex: 1 }} /> )} {option2 && ( <Radio onPress={() => onChange(option2.value)} label={option2.label} checked={option2.value === value} style={{ flex: 1}} /> )} </View> </View> ); } // 处理第三组的单行Radio,循环optionsThree自身的长度 for (let i = 0; i < optionsThree.length; i += 1) { const option3 = optionsThree[i]; // 不存在直接跳过 if (!option3) continue; rows.push( <View key={`single-${i}`}> <View style={{ flexDirection: "row" }}> <Radio onPress={() => onChange(option3.value)} label={option3.label} checked={option3.value === value} style={{ flex: 1 }} /> <View style={{ flex: 1}} /> </View> </View> ); } return ( <View> <View>{rows}</View> </View> );
对应的选项数组用你修改后的版本:
options={[ { label: "label", value: "value" }, { label: "label", value: "value3" }, ]} optionsTwo={[ { label: "label", value: "value2" }, { label: "label", value: "value4" }, { label: "label", value: "value7" }, ]} optionsThree={[ { label: "label", value: "value11" }, // 冗余元素已删除 ]}
更省心的优化方案(推荐)
如果后续要加行或调整布局,建议用统一配置的方式,把每行的左右内容明确定义,维护起来更方便:
// 直接定义每一行的左右内容,一目了然 const rowConfigs = [ { left: options[0], right: optionsTwo[0] }, { left: options[1], right: optionsTwo[1] }, { left: optionsThree[0], right: null }, // 右侧留空占位 ]; // 用map生成所有行,key绝对不会重复 const rows = rowConfigs.map((config, index) => ( <View key={`row-${index}`}> <View style={{ flexDirection: "row" }}> {config.left && ( <Radio onPress={() => onChange(config.left.value)} label={config.left.label} checked={config.left.value === value} style={{ flex: 1 }} /> )} {/* 右侧有内容就放Radio,没有就放占位View */} {config.right ? ( <Radio onPress={() => onChange(config.right.value)} label={config.right.label} checked={config.right.value === value} style={{ flex: 1}} /> ) : ( <View style={{ flex: 1}} /> )} </View> </View> )); return ( <View> <View>{rows}</View> </View> );
这种方式把布局逻辑和数据解耦,新增或修改行只需要调整rowConfigs,不用动循环代码,可读性和维护性更强。
内容的提问来源于stack exchange,提问作者CodingProfile
相关产品推荐
相关产品推荐

