Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/445.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 状态更改后未更新子组件_Javascript_Reactjs - Fatal编程技术网

Javascript 状态更改后未更新子组件

Javascript 状态更改后未更新子组件,javascript,reactjs,Javascript,Reactjs,我正在学习反应,我正在做一个简单的TODOAP。我将JSON文件中的一些todo数据设置为我的应用程序组件的状态,并使用这些值填充子组件。我编写了一个方法,在每次对checkbox元素触发onChange事件时调用该方法,并通过更新状态来翻转复选框。问题是这段代码以前工作得很好,但现在已经不是了。当我更改复选框时,状态会相应地更新,但在子元素中它不会更新,我想知道原因。这是我的密码 App.js import React from "react"; import TodoItem from ".

我正在学习反应,我正在做一个简单的TODOAP。我将JSON文件中的一些todo数据设置为我的应用程序组件的状态,并使用这些值填充子组件。我编写了一个方法,在每次对checkbox元素触发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;
从“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