我正在学习 React,并且正在制作一个简单的 ToDoApp。我在应用程序组件的状态下从 JSON 文件设置了一些待办事项数据,并使用这些值填充子组件。我编写了一个方法,每次在复选框元素上触发 onChange 事件时都会调用该方法,并通过更新状态来翻转复选框。问题是这段代码以前工作得很好,但现在不行了。当我更改复选框时,状态会相应更新,但它不会在子元素中更新,我想知道为什么。这是我的代码
App.js
import React from "react";
import TodoItem from "./TodoItem";
import toDoData from "./toDosData";
class App extends React.Component {
constructor() {
super();
this.state = {
toDoData: toDoData
};
this.handleOnChange = this.handleOnChange.bind(this);
}
handleOnChange(key)
{
this.setState(prevState => {
let newState = prevState.toDoData.map(currentData => {
if(currentData.id === key)
currentData.completed = !currentData.completed;
return currentData;
});
return {toDoData: newState};
});
}
render() {
let toDoComponents = this.state.toDoData.map(toDoDatum =>
<TodoItem key={toDoDatum.id} details={{
key: toDoDatum.id,
text: toDoDatum.text,
completed: toDoDatum.completed,
onChange: this.handleOnChange
}} />);
return (
<div>
{toDoComponents}
</div>
);
}
}
export default App;
TodoItem.js
import React from "react";
class TodoItem extends React.Component {
properties = this.props.details;
render() {
return (
<div>
<input type="checkbox" checked={this.properties.completed}
onChange={() => this.properties.onChange(this.properties.key)}
/>
<span>{this.properties.text}</span>
</div>
)
}
}
export default TodoItem;
提前致谢。
最佳答案
为什么需要将 details
属性分配给类中的 properties
?如果您这样做,properties
不会反射(reflect) prop 更改,并且您的子组件将无法看到更新。只需按原样使用 Prop 即可:
render() {
const { details } = this.props;
return (
<div>
<input
type="checkbox"
checked={details.completed}
onChange={() => details.onChange(details.key)}
/>
<span>{details.text}</span>
</div>
);
}
}
此外,由于您在 TodoItem
组件中不使用任何状态或生命周期方法,因此它也可以是一个功能组件。
const TodoItem = ({ details }) => (
<div>
<input
type="checkbox"
checked={details.completed}
onChange={() => details.onChange(details.key)}
/>
<span>{details.text}</span>
</div>
);
还有一件事,为什么不直接将 todo 本身传递给 TodoItem
呢?
<TodoItem
key={toDoDatum.id}
todo={toDoDatum}
onChange={this.handleOnChange}
/>
和
const TodoItem = ({ todo, onChange }) => (
<div>
<input
type="checkbox"
checked={todo.completed}
onChange={() => onChange(todo.id)}
/>
<span>{todo.text}</span>
</div>
);
这不是更具可读性吗?
评论后更新
const toDoData = [
{ id: 1, text: "foo", completed: false },
{ id: 2, text: "bar", completed: false },
{ id: 3, text: "baz", completed: false }
];
const TodoItem = ({ todo, onChange }) => (
<div>
<input
type="checkbox"
checked={todo.completed}
onChange={() => onChange(todo.id)}
/>
<span>{todo.text}</span>
</div>
);
class App extends React.Component {
constructor() {
super();
this.state = {
toDoData: toDoData
};
this.handleOnChange = this.handleOnChange.bind(this);
}
handleOnChange(key) {
this.setState(prevState => {
let newState = prevState.toDoData.map(currentData => {
if (currentData.id === key)
currentData.completed = !currentData.completed;
return currentData;
});
return { toDoData: newState };
});
}
render() {
let toDoComponents = this.state.toDoData.map(toDoDatum => (
<TodoItem
key={toDoDatum.id}
todo={toDoDatum}
onChange={this.handleOnChange}
/>
));
return <div>{toDoComponents}</div>;
}
}
const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);
<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" />
关于javascript - 状态更改后子组件不更新,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56589261/