更新状态数组对象中的字段
Update field in state array object
我正在用 React 构建一个简单的 TODO 应用程序。我在状态中有一个todos
数组,每个todo
都有一个标志completed
。单击某个项目时,我想切换 todo
的 completed
标志。这是我到目前为止所做的:
Todos.js
class Todos extends React.Component {
constructor() {
super();
this.state = {
todos: [
{ id:0, title:"Title 0", completed:false },
{ id:1, title:"Title 1", completed:true }
]
};
this.onTodoClicked = this.onTodoClicked.bind(this);
}
onTodoClicked(id) {
console.log(id + " clicked");
this.setState(prevState => {
todos: prevState.todos.map((item, index) => {
return index !== id ? item : { ...item, completed: !item.completed };
});
});
}
render() {
return (
<div>
{this.state.todos.map((todoItem, key) => (
<Todo id={key} key={key} todo={todoItem}
todoClicked={this.onTodoClicked} />
))}
</div>
);
}
}
Todo.js 只是一个简单的组件(是的,它也可以发挥作用)
class Todo extends React.Component {
render() {
return (
<div onClick={() => this.props.todoClicked(this.props.id)}>
{this.props.todo.title}
</div>
);
}
}
在Todos.js中调用函数onTodoClicked
并打印出正确的id,但状态没有其他变化(我检查了点击的使用 React 开发工具和 console.log 的对象)。单击的项目不会更改其 completed
标志。我做错了什么?
最好依靠 id
,而不是 index
:
return item.id !== id ? item : { ...item, completed: !item.completed };
另外,对于 Todo
id,您应该传递 id,而不是键 (id={key}
)(或者只传递整个 todoItem):
id={todoItem.id}
对于 Todo
键也传递 id
,因为传递相同的 key
索引,您的 Todo
项目可能不会重新呈现。
最后,您在 prevState => ({
之后缺少括号
class Todo extends React.Component {
render() {
return (
<div onClick={() => this.props.todoClicked(this.props.todo.id)}>
{this.props.todo.title} - {this.props.todo.completed.toString()}
</div>
);
}
}
class Todos extends React.Component {
constructor() {
super();
this.state = {
todos: [
{ id:0, title:"Title 0", completed:false },
{ id:1, title:"Title 1", completed:true }
]
};
this.onTodoClicked = this.onTodoClicked.bind(this);
}
onTodoClicked(id) {
console.log(id);
this.setState(prevState => ({
todos: prevState.todos.map((item, index) => {
return item.id !== id ? item : { ...item, completed: !item.completed };
})
}));
}
render() {
return (
<div>
{this.state.todos.map((todoItem, key) => (
<Todo key={todoItem.id} todo={todoItem}
todoClicked={this.onTodoClicked} />
))}
</div>
);
}
}
ReactDOM.render(<Todos />, document.querySelector("#container"))
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
<div id="container"></div>
您必须更改 onTodoClicked Function.it 才会起作用。
onTodoClicked(id) {
console.log(id + " clicked");
this.state.todos[id].completed = !this.state.todos[id].completed;
this.setState({ todos: this.state.todos });
console.log("state,", this.state.todos);
}
这是link:https://stackblitz.com/edit/react-yxxksp?file=index.js
应该是这样的:
class Todos extends React.Component {
constructor() {
super();
this.state = {
todos: [
{ id:0, title:"Title 0", completed:false },
{ id:1, title:"Title 1", completed:true }
]
};
this.onTodoClicked = this.onTodoClicked.bind(this);
}
onTodoClicked(id) {
console.log(id + " clicked");
this.setState(prevState => ({
todos: prevState.todos.map((item, index) => {
return item.id !== id ? item : { ...item, completed: !item.completed };
})
}));
}
render() {
return (
<div>
{this.state.todos.map((todoItem, key) => (
<Todo key={key} todo={todoItem}
todoClicked={this.onTodoClicked} />
))}
</div>
);
}
}
class Todo extends React.Component {
render() {
return (
<div onClick={() => this.props.todoClicked(this.props.todo.id)}>
{this.props.todo.title} {this.props.todo.completed && "completed"}
</div>
);
}
}
ReactDOM.render(<Todos/>, document.getElementById("root"))
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
<div id="root"></div>
这是您在 Todo.js
中可以做的
class Todo extends React.Component {
render() {
return (
<div onClick={() => this.props.todoClicked(this.props.todo.id)}>
{this.props.todo.title}
</div>
);
}
}
在 onTodoClicked 函数中,你可以做这样的事情。
onTodoClicked(id) {
this.setState(prevState => {
todos: prevState.todos.map((item) => {
return item.id !== id ? item : { ...item, completed: !item.completed };
});
});
}
希望对您有所帮助。
我正在用 React 构建一个简单的 TODO 应用程序。我在状态中有一个todos
数组,每个todo
都有一个标志completed
。单击某个项目时,我想切换 todo
的 completed
标志。这是我到目前为止所做的:
Todos.js
class Todos extends React.Component {
constructor() {
super();
this.state = {
todos: [
{ id:0, title:"Title 0", completed:false },
{ id:1, title:"Title 1", completed:true }
]
};
this.onTodoClicked = this.onTodoClicked.bind(this);
}
onTodoClicked(id) {
console.log(id + " clicked");
this.setState(prevState => {
todos: prevState.todos.map((item, index) => {
return index !== id ? item : { ...item, completed: !item.completed };
});
});
}
render() {
return (
<div>
{this.state.todos.map((todoItem, key) => (
<Todo id={key} key={key} todo={todoItem}
todoClicked={this.onTodoClicked} />
))}
</div>
);
}
}
Todo.js 只是一个简单的组件(是的,它也可以发挥作用)
class Todo extends React.Component {
render() {
return (
<div onClick={() => this.props.todoClicked(this.props.id)}>
{this.props.todo.title}
</div>
);
}
}
在Todos.js中调用函数onTodoClicked
并打印出正确的id,但状态没有其他变化(我检查了点击的使用 React 开发工具和 console.log 的对象)。单击的项目不会更改其 completed
标志。我做错了什么?
最好依靠 id
,而不是 index
:
return item.id !== id ? item : { ...item, completed: !item.completed };
另外,对于 Todo
id,您应该传递 id,而不是键 (id={key}
)(或者只传递整个 todoItem):
id={todoItem.id}
对于 Todo
键也传递 id
,因为传递相同的 key
索引,您的 Todo
项目可能不会重新呈现。
最后,您在 prevState => ({
class Todo extends React.Component {
render() {
return (
<div onClick={() => this.props.todoClicked(this.props.todo.id)}>
{this.props.todo.title} - {this.props.todo.completed.toString()}
</div>
);
}
}
class Todos extends React.Component {
constructor() {
super();
this.state = {
todos: [
{ id:0, title:"Title 0", completed:false },
{ id:1, title:"Title 1", completed:true }
]
};
this.onTodoClicked = this.onTodoClicked.bind(this);
}
onTodoClicked(id) {
console.log(id);
this.setState(prevState => ({
todos: prevState.todos.map((item, index) => {
return item.id !== id ? item : { ...item, completed: !item.completed };
})
}));
}
render() {
return (
<div>
{this.state.todos.map((todoItem, key) => (
<Todo key={todoItem.id} todo={todoItem}
todoClicked={this.onTodoClicked} />
))}
</div>
);
}
}
ReactDOM.render(<Todos />, document.querySelector("#container"))
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
<div id="container"></div>
您必须更改 onTodoClicked Function.it 才会起作用。
onTodoClicked(id) {
console.log(id + " clicked");
this.state.todos[id].completed = !this.state.todos[id].completed;
this.setState({ todos: this.state.todos });
console.log("state,", this.state.todos);
}
这是link:https://stackblitz.com/edit/react-yxxksp?file=index.js
应该是这样的:
class Todos extends React.Component {
constructor() {
super();
this.state = {
todos: [
{ id:0, title:"Title 0", completed:false },
{ id:1, title:"Title 1", completed:true }
]
};
this.onTodoClicked = this.onTodoClicked.bind(this);
}
onTodoClicked(id) {
console.log(id + " clicked");
this.setState(prevState => ({
todos: prevState.todos.map((item, index) => {
return item.id !== id ? item : { ...item, completed: !item.completed };
})
}));
}
render() {
return (
<div>
{this.state.todos.map((todoItem, key) => (
<Todo key={key} todo={todoItem}
todoClicked={this.onTodoClicked} />
))}
</div>
);
}
}
class Todo extends React.Component {
render() {
return (
<div onClick={() => this.props.todoClicked(this.props.todo.id)}>
{this.props.todo.title} {this.props.todo.completed && "completed"}
</div>
);
}
}
ReactDOM.render(<Todos/>, document.getElementById("root"))
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
<div id="root"></div>
这是您在 Todo.js
中可以做的class Todo extends React.Component {
render() {
return (
<div onClick={() => this.props.todoClicked(this.props.todo.id)}>
{this.props.todo.title}
</div>
);
}
}
在 onTodoClicked 函数中,你可以做这样的事情。
onTodoClicked(id) {
this.setState(prevState => {
todos: prevState.todos.map((item) => {
return item.id !== id ? item : { ...item, completed: !item.completed };
});
});
}
希望对您有所帮助。