index用作时发生此错误
key。React使用该
key属性来跟踪列表中的元素。当您从数组中间删除元素时,索引不会删除自身,而是会重新排列,最后一个索引会消失。这就是为什么数组中的最后一个元素总是被删除的原因。
对于此解决方案,我提供
title的注释为
key,但这可能并不总是唯一的。使用生成的密钥或字段组合作为密钥会更好
class NoteEntry extends React.Component { constructor(props) { super(props); this.state = { display: false, editing: false, editTitle: this.props.title, editDetails: this.props.details } this.displayToggle = this.displayToggle.bind(this); this.edit = this.edit.bind(this); this.save = this.save.bind(this); } displayToggle() { this.setState(prevState => ({ display: !prevState.display })) } edit() { this.setState({ editing: true }) } save() { let titleval = this.refs.updateTitle.value; let detailsVal = this.refs.updateDetails.value; this.setState({ editTitle: titleval, editDetails: detailsVal, editing: false }) } render() { return ( <div className="entry"> <div className="entry-header" onClick={this.state.editing ? null : this.displayToggle}> {this.state.editing ? ( <input ref="updateTitle" className="edit-title" type="text" defaultValue={this.state.editTitle} /> ) : ( <h2 className="entry-title">{this.state.editTitle}</h2> )} <p className="timestamp">{this.displayTime}</p> </div> <hr /> <div className={"entry-content " + (!this.state.display ? "hide-details" : null)}> {this.state.editing ? ( <textarea ref="updateDetails" className="edit-details" cols="10" rows="2" defaultValue={this.state.editDetails}></textarea> ) : ( <p className="details">{this.state.editDetails}</p> )} <div className="entry-buttons"> {this.state.editing ? ( <button className="save" onClick={this.save}>Save</button> ) : ( <button className="edit" onClick={this.edit}>Edit</button> ) } <button className="delete" onClick={this.props.deleteNote}>Delete</button> </div> </div> </div> ) }}const NoteForm = (props) => { return ( <div> <form className="form-section"> <input className="title-input" type="type" placeholder="Title" value={props.titlevalue} onChange={props.titleHandle} /> <br /> <textarea className="details-input" cols="20" rows="3" placeholder="Details" value={props.detailsValue} onChange={props.detailsHandle} /> <br /> <button className="input-button" onClick={props.onSubmit}> Add Note </button> </form> </div> )}class App extends React.Component { constructor(props) { super(props); this.state = { notes: [], title: "", details: "" } this.updateTitle = this.updateTitle.bind(this); this.updateDetails = this.updateDetails.bind(this); this.submitHandler = this.submitHandler.bind(this); this.deleteHandler = this.deleteHandler.bind(this); } updateTitle(event) { this.setState({ title: event.target.value }); } updateDetails(event) { this.setState({ details: event.target.value }); } submitHandler(e) { e.preventDefault(); if (!this.state.title.length || !this.state.details.length) { return; } const newNote = { newTitle: this.state.title, newDetails: this.state.details } this.setState(prevState => ({ notes: prevState.notes.concat(newNote), title: "", details: "" })) } deleteHandler(id) { this.setState(prevState => ({ notes: prevState.notes.filter((el)=> el !== id) })) } render() { return ( <div className="container"> <h1 className="title">React Notes App</h1> <NoteForm titlevalue={this.state.title} detailsValue={this.state.details} titleHandle={this.updateTitle} detailsHandle={this.updateDetails} onSubmit={this.submitHandler} /> <div className="entry-section"> {this.state.notes.map((note,i) => ( <NoteEntry key={note.newTitle} title={note.newTitle} details={note.newDetails} deleteNote={this.deleteHandler.bind(this,note)} /> ))} </div> </div> ); }}ReactDOM.render(<App />, document.getElementById('root'));<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script><script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script><div id="root"></div>


