我一直在努力理解React概念,并做了我的Todo项目。我显示了虚拟数据,但是无法向我的虚拟数据添加新值,该值存储在对象数组中的单独文件todos.js中。
这是file hierarchy
这是我得到的错误-index.js:2177 Warning: Each child in an array or iterator should have a unique "key" prop.
TodoList.js
import React from 'react';
import Todo from './Todo';
import todos from '../todos'
class TodoList extends React.Component {
constructor() {
super();
this.state = {
todoItems: todos,
newItem: {}
}
}
addItem = (event) => {
event.preventDefault();
const todoList = this.state.todoItems;
todoList.push(this.state.newItem);
this.setState({
todoList: todos,
newItem: {}
});
};
handleInput = (event) => {
this.setState({ newItem: event.target.value });
}
render() {
const itenary = this.state.todoItems;
return (
<div>
{itenary.map(todo =>
<div key={todo.id}>
<Todo handleClick={this.props.handleClick} thing={todo} />
</div>
)}
<br />
<form onSubmit={this.addItem}>
<input type="text" onChange={this.handleInput} placeholder="Add a new task" />
<button>Submit</button>
</form>
</div>
);
}
}
export default TodoList;
Todo.js
import React from 'react';
class Todo extends React.Component {
constructor() {
super();
this.state = {
clicked: false
}
}
handleClick = () => {
this.setState({ clicked: !this.state.clicked });
}
render() {
const styles = this.state.clicked ? { textDecoration: 'line-through' } : { textDecoration: 'none' };
return (
{/* This is where the todo item is*/}
<div style={styles} onClick={this.handleClick} key={this.props.thing.id}>{this.props.thing.text}</div>
);
}
}
export default Todo;
todos.js
const todos = [
{ id: 1, text: 'Go to the gym', 'completed': false },
{ id: 2, text: 'Do laundry', 'completed': false },
{ id: 3, text: 'Study for exams', 'completed': false },
{ id: 4, text: 'Read a book', 'completed': false },
{ id: 5, text: 'Clean the bedroom', 'completed': false },
{ id: 6, text: 'Go to the park', 'completed': false },
];
export default todos;
任何帮助和/或反馈表示赞赏。
最佳答案
您必须为添加到todoItems
的新待办事项赋予唯一的id
,当渲染它们时,React可以使用它来区分其他待办事项。
您也不应使用push
更改当前状态。相反,您应该使用一个全新的数组设置状态,该数组包含先前数组所做的所有操作。
例
class TodoList extends React.Component {
constructor() {
super();
this.state = {
todoItems: todos,
newItem: ""
};
}
addItem = event => {
event.preventDefault();
this.setState(prevState => {
return {
todoItems: [
...prevState.todoItems,
{ id: Math.random(), text: prevState.newItem, completed: false }
],
newItem: ""
};
});
};
// ...
}
const todos = [
{ id: 1, text: "Go to the gym", completed: false },
{ id: 2, text: "Do laundry", completed: false },
{ id: 3, text: "Study for exams", completed: false },
{ id: 4, text: "Read a book", completed: false },
{ id: 5, text: "Clean the bedroom", completed: false },
{ id: 6, text: "Go to the park", completed: false }
];
class TodoList extends React.Component {
constructor() {
super();
this.state = {
todoItems: todos,
newItem: ""
};
}
addItem = event => {
event.preventDefault();
this.setState(prevState => {
return {
todoItems: [
...prevState.todoItems,
{ id: Math.random(), text: prevState.newItem, completed: false }
],
newItem: ""
};
});
};
handleInput = event => {
this.setState({ newItem: event.target.value });
};
render() {
const itenary = this.state.todoItems;
return (
<div>
{itenary.map(todo => (
<div key={todo.id}>
<Todo handleClick={this.props.handleClick} thing={todo} />
</div>
))}
<br />
<form onSubmit={this.addItem}>
<input
type="text"
onChange={this.handleInput}
value={this.state.newItem}
placeholder="Add a new task"
/>
<button>Submit</button>
</form>
</div>
);
}
}
class Todo extends React.Component {
constructor() {
super();
this.state = {
clicked: false
};
}
handleClick = () => {
this.setState({ clicked: !this.state.clicked });
};
render() {
const styles = this.state.clicked
? { textDecoration: "line-through" }
: { textDecoration: "none" };
return (
<div style={styles} onClick={this.handleClick} key={this.props.thing.id}>
{this.props.thing.text}
</div>
);
}
}
ReactDOM.render(<TodoList />, 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>