我在调试这种情况时遇到问题。我正在尝试从 API 提供的数组中删除索引。在检查其父级的道具更改后,我将其存储在父级状态中。这里一切都很好。我可以将任何道具更改存储在父表单状态中。父表单映射templateData中的所有内容,我确定它是什么类型,然后根据需要渲染一个组件。删除按钮将始终只在DynamicInputGroup中,因此我通过道具向下传递该功能。在DynamicInputGroup中,我需要映射从父级传递的数组,然后映射该数组中的对象以显示每个单独的输入。再次使用传递下来的道具来确定要渲染的输入,与父级相同。这是出了问题的地方。当我单击删除时,假设索引 2(共 5 个),我看到该索引在状态中被删除,但呈现的是索引 5 被删除。我不确定该怎么做。我已经完成研究并阅读了密钥发挥作用?我试图将渲染函数中的一个变量设置为状态,这样它就会刷新,但什么也没有。最后一个索引总是被删除。哈!家长表格this.state = { templateData: []}removeGroupItem = (index, inputName ) => { let group = `${inputName}__group` const newState = this.state; if (index === -1) return; newState.templateData[group].splice(index, 1); console.log(newState) // THIS SHOWS CORRECT STATE this.setState(newState);}render() { return ( {Object.keys(this.state.templateData).map((name, key) => { let data = { // SETTING inputType TO DISPLAY CORRECT COMPONENT } return ( <Fragment key={key}> {data.inputType == 'input' && <DynamicTextInput {...data} />} {data.inputType == 'rtf' && <DynamicRTF {...data} />} {data.inputType == 'img' && <DynamicImageUpload {...data} />} {data.inputType == 'group' && <DynamicInputGroup {...data} removeGroupItem={this.removeGroupItem} />} // COMPONENT THAT HOLDS REMOVE BUTTON </Fragment> ) })} )}动态输入组组件this.state = { value: []}componentDidMount() { this.setState({ value: this.props.value })}componentDidUpdate(prevProps) { if (this.props.value !== prevProps.value) { this.setState({ value: this.props.value }) }}
2 回答
慕的地8271018
TA贡献1796条经验 获得超4个赞
使用索引作为组件的键是一种不好的做法,尤其是当它是一个不断变化的列表时。键应该是组件的唯一标识符。
如果您的控件没有唯一标识符,您可以基于时间戳创建一个标识符,某种 uuid,您将存储在您的状态中,并且始终只引用一个控件元素。
想象一下,您有 1 个输入元素的值为 的情况TextInput 1
。然后你从它添加另一个输入,它继承它的密钥。现在您已经破坏了影子 DOM,因为您引用的是新输入而不是旧输入,因为带有 key={0} 的输入的值为TextInput 1
,但这不是您所期望的,因为您想要引用另一个输入。
慕慕森
TA贡献1856条经验 获得超17个赞
这一行有问题:
<Fragment key={key}>
由于您使用数组的索引来呈现那些Fragments
,协调失败length
次数和“最后一个元素”被删除。
添加回答
举报
0/150
提交
取消