我有一个Main.js页面,其中有一个按钮:单击它时,它将向数组和页面添加一个Block组件。您可以根据需要添加任意数量的块组件。每个“块”组件都有一个“删除”按钮,该按钮将从阵列和页面中删除该块。
Menu.js:
import React from 'react';
import './Menu.css';
import Block from './Block.js';
import './Block.css';
export default class Menu extends React.Component {
constructor(props) {
super(props);
this.state = { value: '', blocksArray: [] };
this.addBlock = this.addBlock.bind(this);
this.removeBlock = this.removeBlock.bind(this);
this.blocks = [];
}
addBlock() {
this.blocks.push({ title: 'Section title' + this.blocks.length, content: 'Content' + this.blocks.length });
this.setState({ value: '', blocksArray: this.blocks });
}
removeBlock(index) {
this.blocks.splice(index, 1);
this.setState({ value: '', blocksArray: this.blocks })
}
renderBlocks = () => {
return (
this.state.blocksArray.map((block, index) =>
<Block
remove={() => this.removeBlock(index)}
key={index}
title={block.title}
content={block.content}
/>
)
)
}
render() {
return (
<div>
<div className="Menu">
<header className="Menu-header">
<button className="Menu-button" onClick={ () => this.addBlock() }>Add block</button>
</header>
</div>
<div>
{ this.renderBlocks() }
</div>
</div>
);
}
}
Block.js(版本1)
import React from 'react';
import './Block.css';
class Block extends React.Component {
constructor(props) {
super(props);
this.state = {
title: props.title,
content: props.content,
remove: props.remove
};
this.handleChange = this.handleChange.bind(this);
this.handleSubmit = this.handleSubmit.bind(this);
}
handleChange(event) {
this.setState({[event.target.name]: event.target.value});
}
handleSubmit(event) {
//alert('A name was submitted: ' + this.state.title);
event.preventDefault();
}
render() {
return (
<div className="Block-container">
<form onSubmit={this.handleSubmit}>
<div className="Block-title">
<label>
Title:
<input type="text" name="title" value={this.props.title} onChange={this.handleChange} />
</label>
</div>
<div className="Block-content">
<label>
Content:
<input type="text" name="content" value={this.props.content} onChange={this.handleChange} />
</label>
</div>
<input type="submit" value="Save" />
<input type="button" value="Delete" onClick= { () => this.state.remove() } />
</form>
</div>
);
}
}
export default Block;
问题:我发现自己陷入了两种情况,但都无法正常工作。
第一个Block.js无效解决方案:
<input type="text" name="title" value={this.props.title} onChange={this.handleChange} />
<input type="text" name="content" value={this.props.content} onChange={this.handleChange} />
如果我在块上按下删除按钮时使用value = {this.props.content}和value = {this.props.title},它可以工作,但是我无法在该字段中编辑文本因为它的值始终是从道具中获取的。
Block.js的第二个无效解决方案:
<input type="text" name="title" value={this.state.title} onChange={this.handleChange} />
<input type="text" name="content" value={this.state.content} onChange={this.handleChange} />
如果我使用value = {this.state.content}和value = {this.state.title},我可以编辑文本字段,当我按下Block上的Delete按钮时,它会从数组中正确删除组件, 但在字段中显示的文本是错误的(好像总是只弹出数组中的最后一个组件一样)。让我用一些屏幕截图进行解释。
假设我添加了4个Block组件,如下所示:
然后,单击带有“ Section title1” /“ Content1”的块的删除按钮,如下图所示:
它显然删除了数组中的正确元素,但是由于某种原因,我在组件中得到了错误的文本:
阵列console.log:
0: Object { title: "Section title0", content: "Content0" }
1: Object { title: "Section title2", content: "Content2" }
2: Object { title: "Section title3", content: "Content3" }
显示的文字:
我显然错过了一些东西,并且被困了一段时间。有人可以解释出什么问题吗?
答案 0 :(得分:2)
我认为问题在于您正在将index设置为每个Block的键。 原始键为[0,1,2,3]。当您删除Section title1时,新的渲染将产生关键帧[0,1,2]。因此,React假定键[0、1、2]的元素未更改,而键3被删除。因此,它删除了最后一个。 尝试对键使用唯一的属性。 您可以在此处了解更多信息:https://reactjs.org/docs/reconciliation.html#keys
答案 1 :(得分:1)
您的更改处理程序需要在标题/内容来自的父组件中的状态下运行。块中显示的值是从菜单的状态读取的,因此在编辑块数据时会更改其自身的内部状态,因为道具内部的状态不会被反馈,所以从菜单到块的值保持不变
您可以在菜单状态下编写一个函数来编辑数组:
this.editBlock = this.editBlock.bind(this);
...
editBlock(index, newBlock) {
let blocks = Array.from(this.state.blocksArray);
blocks[index] = newBlock;
this.setState({
blocksArray: blocks
})
}
然后将其作为道具传递给Block并在change事件触发时调用它:
<Block
remove={() => this.removeBlock(index)}
key={index}
title={block.title}
content={block.content}
index={index}
editBlock={this.editBlock}
/>
handleChange(event) {
this.setState({[event.target.name]: event.target.value}, () => {
this.props.editBlock(this.props.index, { title: this.state.title, content: this.state.content})
});
}
正在运行的演示here。