Javascript 状态更改后未更新子组件
我正在学习反应,我正在做一个简单的TODOAP。我将JSON文件中的一些todo数据设置为我的应用程序组件的状态,并使用这些值填充子组件。我编写了一个方法,在每次对checkbox元素触发onChange事件时调用该方法,并通过更新状态来翻转复选框。问题是这段代码以前工作得很好,但现在已经不是了。当我更改复选框时,状态会相应地更新,但在子元素中它不会更新,我想知道原因。这是我的密码 App.jsJavascript 状态更改后未更新子组件,javascript,reactjs,Javascript,Reactjs,我正在学习反应,我正在做一个简单的TODOAP。我将JSON文件中的一些todo数据设置为我的应用程序组件的状态,并使用这些值填充子组件。我编写了一个方法,在每次对checkbox元素触发onChange事件时调用该方法,并通过更新状态来翻转复选框。问题是这段代码以前工作得很好,但现在已经不是了。当我更改复选框时,状态会相应地更新,但在子元素中它不会更新,我想知道原因。这是我的密码 App.js import React from "react"; import TodoItem from ".
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;
从“React”导入React;
从“/TodoItem”导入TodoItem;
从“/toDosData”导入toDoData;
类应用程序扩展了React.Component{
构造函数(){
超级();
此.state={
托多达塔:托多达塔
};
this.handleOnChange=this.handleOnChange.bind(this);
}
换把手(钥匙)
{
this.setState(prevState=>{
让newState=prevState.toDoData.map(currentData=>{
if(currentData.id==键)
currentData.completed=!currentData.completed;
返回当前数据;
});
返回{toDoData:newState};
});
}
render(){
让toDoComponents=this.state.toDoData.map(toDoDatum=>
);
返回(
{toDoComponents}
);
}
}
导出默认应用程序;
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;
从“React”导入React;
类TodoItem扩展了React.Component{
属性=this.props.details;
render(){
返回(
this.properties.onChange(this.properties.key)}
/>
{this.properties.text}
)
}
}
将默认值导出到doitem;
提前感谢。为什么您需要将您的
详细信息
道具指定给您的班级中的属性
?如果您这样做,属性
不会反映道具更改,并且您的子组件无法看到更新。只需按原样使用道具即可:
render() {
const { details } = this.props;
return (
<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})=>(
onChange(todo.id)}
/>
{todo.text}
);
这不是更可读吗
评论后更新
const toDoData=[
{id:1,文本:“foo”,完成:false},
{id:2,文本:“bar”,已完成:false},
{id:3,文本:“baz”,完成:false}
];
const TodoItem=({todo,onChange})=>(
onChange(todo.id)}
/>
{todo.text}
);
类应用程序扩展了React.Component{
构造函数(){
超级();
此.state={
托多达塔:托多达塔
};
this.handleOnChange=this.handleOnChange.bind(this);
}
换把手(钥匙){
this.setState(prevState=>{
让newState=prevState.toDoData.map(currentData=>{
if(currentData.id==键)
currentData.completed=!currentData.completed;
返回当前数据;
});
返回{toDoData:newState};
});
}
render(){
让toDoComponents=this.state.toDoData.map(toDoDatum=>(
));
返回{toDoComponents};
}
}
const rootElement=document.getElementById(“根”);
render(,rootElement)代码>
为什么您需要将您的详细信息
道具指定给班级中的属性
?如果您这样做,属性
不会反映道具更改,并且您的子组件无法看到更新。只需按原样使用道具即可:
render() {
const { details } = this.props;
return (
<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})=>(
onChange(todo.id)}
/>
{todo.text}
);
这不是更可读吗
评论后更新
const toDoData=[
{id:1,文本:“foo”,完成:false},
{id:2,文本:“bar”,已完成:false},
{id:3,文本:“baz”,完成:false}
];
const TodoItem=({todo,onChange})=>(
onChange(todo.id)}
/>
{todo.text}
);
类应用程序扩展了React.Component{
构造函数(){
超级();
此.state={
托多达塔:托多达塔
};
this.handleOnChange=this.handleOnChange.bind(this);
}
换把手(钥匙){
this.setState(prevState=>{
让newState=prevState.toDoData.map(currentData=>{
if(currentData.id==键)
currentData.completed=!currentData.completed;
返回当前数据;
});
返回{toDoData:newState};
});
}
render(){
让toDoComponents=this.state.toDoData.map(toDoDatum=>(
));
返回{toDoComponents};
}
}
const rootElement=document.getElementById(“根”);
render(,rootElement)代码>
感谢您的快速回答。事实上,我做了你之前建议的关于使用道具的更改。当我点击复选框时,它仍然没有更新…哦,谢谢你的建议,它实际上更容易阅读,除非我们看到一个工作示例,否则我们什么都不能说。但是,我已经编辑了我的答案,并添加了一个工作代码和我的建议。我觉得很好。谢谢,我复制粘贴了你的代码,它成功了,但我仍然无法找出我在这里做错了什么,因为它看起来和我的代码一样。谢谢。你不知道我做这件事多久了,不客气。正如我在回答中所说的,如果您将道具设置为类实例,那么它不会反映更改。这就是为什么我们在React中有状态和道具。不要弄乱那些道具:)照原样使用它们。顺便说一下,你不需要使用我的确切代码。如果您更喜欢,它将与详细信息一起使用。但是,我认为你在那里挣扎得太多了:)这里的关键是你应该使用道具!在代码的主要部分t