javascript - Checkbox 在 React todo 应用程序中单击时不会更改其值
问题描述
请帮我解决这个问题,我不明白我在哪里做错了。因此,当我单击复选框时,值不会改变(如果默认情况下true
,当我单击单击时它应该是false
)。为此,我onChange
在todoList
组件中调用handleClick
函数,我更改了todo.completed
值(基本上是切换值)。
在方法App.js
内部handleClick
当console.log(todo)
从地图函数返回之前做的时候可以正常切换,但它没有在updatedTodo
.
应用程序.js
import TodosData from "./todoData";
import TodoList from "./todoList";
import "./styles.css";
class App extends Component {
constructor() {
super();
this.state = {
todos: TodosData
}
this.handleChange = this.handleChange.bind(this)
}
handleChange(id) {
this.setState(prevState => {
const updatedTodo = prevState.todos.map(todo => {
// console.log(updatedTodo);
if(todo.id === id) {
console.log("before the opt "+todo.completed);
todo.completed = !todo.completed
console.log("after the opt "+todo.completed);
}
//console.log(todo);
return todo;
})
console.log(updatedTodo);
return {
todos: updatedTodo
}
});
}
render() {
const todoDataComponents = this.state.todos.map(item => {
return <TodoList key = {item.id} item = {item} handleChange = {this.handleChange} />
})
return (
<div className="todo-list">{todoDataComponents}</div>
);
}
}
export default App;
todoList.jsx
class TodoList extends Component {
constructor(props) {
super(props);
this.state = {}
}
render() {
// console.log(this.props)
return (
<div className="todo-item">
<input
type="checkbox"
checked={this.props.item.completed}
onChange = {() => this.props.handleChange(this.props.item.id)}
/>
<p>{this.props.item.text}</p>
</div>
);
}
}
export default TodoList;
todoData.js
const TodosData = [
{ id: 1, text: "Coding", completed: true },
{ id: 2, text: "Exercise", completed: false },
{ id: 3, text: "Learning", completed: true },
{ id: 4, text: "Programming", completed: true },
{ id: 5, text: "inspire", completed: false },
{ id: 6, text: "motivation", completed: true }
];
export default TodosData;
解决方案
我在您的方法中看不到任何错误handleChange()
,它应该可以正常工作。但是,我刚刚更新了您可以在下面测试的一些代码。
我改变了你的名字,TodoList
因为它不是一个真正的列表,而是一个项目。我还将它更改为功能组件,因为它只是展示性的,不需要拥有自己的状态。而不是在 之后添加p
标签input
,您应该使用 alabel
使其可访问。
我并没有真正改变你的handleChange()
方法中的任何东西,只是删除了console.log
s 并且它按预期工作。
更新:您正在使用React.StrictMode
,其中 React 在 dev 上渲染所有内容两次。当您handleChange()
运行两次时,它会将单击的待办事项的completed
状态设置两次,使其恢复到原始状态。因此,如果它false
在第一次渲染时设置为true
单击,但它会再次渲染,在第二次渲染时又回到false
. 你不会注意到它,因为它非常快。
为了避免它,你需要避免改变任何东西。所以我更新了你的onChange
处理程序,如果completed
属性发生变化,它会返回一个新对象。
随意运行下面的代码片段并单击复选框或项目文本。
const TodosData = [
{ id: 1, text: 'Coding', completed: true },
{ id: 2, text: 'Exercise', completed: false },
{ id: 3, text: 'Learning', completed: true },
{ id: 4, text: 'Programming', completed: true },
{ id: 5, text: 'Inspire', completed: false },
{ id: 6, text: 'Motivation', completed: true },
];
function TodoItem(props) {
const { handleChange, item } = props;
return (
<div className="todo-item">
<input
type="checkbox"
id={`item-${item.id}`}
checked={item.completed}
onChange={() => handleChange(item.id)}
/>
<label htmlFor={`item-${item.id}`}>{item.text}</label>
</div>
);
}
class App extends React.Component {
constructor() {
super();
this.state = {
todos: TodosData,
};
this.handleChange = this.handleChange.bind(this);
}
handleChange(id) {
this.setState((prevState) => {
const updatedTodo = prevState.todos.map((todo) => {
return todo.id === id ? {
...todo,
completed: !todo.completed,
} : todo;
});
return {
todos: updatedTodo,
};
});
}
render() {
const { todos } = this.state;
return (
<div className="todo-list">
{todos.map((item) => (
<TodoItem
key={item.id}
item={item}
handleChange={this.handleChange}
/>
))}
</div>
);
}
}
ReactDOM.render(
<React.StrictMode>
<App />
</React.StrictMode>,
document.getElementById('root')
);
body {
font-family: sans-serif;
line-height: 1.6;
}
<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>
推荐阅读
- javascript - Ng-仅在特定页面上显示按钮
- php - 不显示 SESSION ITEM / VARIABLE codeIgniter
- java - FileOutputStream 不显示 FileNotFoundException
- swift4 - Swift 4,有没有办法在不使用 capturePhoto 的情况下捕捉高质量的照片?
- c# - 如果在单独的线程中实例化,如何将 WPF MessageBox 保持在顶部
- javascript - 反应原生 - 在组件内插入图像
- html - 复选框未在 div 标签内对齐
- node.js - 如何将查询字符串传递给中间件函数?
- html - 如何将这些箭头垂直居中对齐?
- c - 在 C 中,我无法获取成员结构(双指针)的指向值。该值在分配该值的函数之外丢失