父组件状态更新后,组件不会更新

时间:2019-01-26 21:27:21

标签: javascript reactjs

.revalidate

嗨,

我是个新手,所以这是我的子组件,它从其父组件获取状态。我的目标是每次更改数组import React, {Component} from 'react'; import "./DisplayCard.css"; class DisplayCard extends Component { runArray = (array) => { for (var i = 0; i<array.length; i++) { return <div>{array[i].task}</div> } } renderElements = (savedTasks) =>{ if (savedTasks.length === 0) { return <div className="noTasks"> <p>You have no saved tasks.</p> </div> } else { return this.runArray(savedTasks) } } render() { return ( <div className="DisplayCardContainer"> {this.renderElements(this.props.saved)} </div> ) } } export default DisplayCard; 时重新渲染组件。

此组件呈现this.props.saved时为<p>You have no saved tasks.</p>,当我输入第一个任务时呈现this.props.saved.length === 0,但此后它仍为<div>{array[0].task}</div>。我确实看到状态不断变化,<div>{array[0].task}</div>不断扩大,但是我的组件不再变化。

5 个答案:

答案 0 :(得分:2)

这是您的问题:

runArray = (array) => {
   for (var i = 0; i<array.length; i++) {
     //the first time we get here, it immediately ends the function!
     return <div>{array[i].task}</div>
   }
}

此循环仅经历一次(在i=0),然后返回,退出runArray函数并取消循环的其余部分。您可能想返回一个元素数组,每个任务一个。我建议为此使用Array.map(),它需要一个数组并转换每个元素,从而创建一个新数组:

runArray = (array) => {
    return array.map(arrayElement => <div>arrayElement.task</div>);
}

这应该可以解决问题。请注意,React可能会抱怨您的元素缺少key属性的事实-有关更多信息,请参见文档:https://reactjs.org/docs/lists-and-keys.html

答案 1 :(得分:1)

问题出在您的runArray函数中。在循环内部,您将返回第一个元素,仅此而已。我的猜测是,您只看到第一个条目?

当您尝试呈现所有任务时,建议您映射任务,例如

runArray = (array) => array.map(entry => <div>{entry.task}</div>)

答案 2 :(得分:1)

这是因为您写错了runArray函数。您在for循环中返回一个值,这样它在第一次迭代后就中断了。它不会遍历整个数组。

您需要将for循环转换为地图:https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map

runArray = (array) => {
  return array.map(v => <div>{v.task}</div>)
}

它可以解决您的问题吗?

答案 3 :(得分:0)

您必须更新组件的状态才能触发渲染功能。未触发渲染功能,因为在更改道具时未更新状态。道具更新时,有多种更新状态的方法。一种方法可能如下:

componentWillReceiveProps(nextProps){
  if (nextProps.saved !== this.props.saved) {
    this.setState({ saved: nextProps.saved })
  }
}

还可以更改渲染功能以使用组件的状态,如下所示:

renderElements = () =>{
  if (this.state.savedTasks.length === 0) {
    return <div className="noTasks"> <p>You have no saved tasks.</p> </div>
  } else {
    return this.runArray(this.state.savedTasks)
  }
}

答案 4 :(得分:0)

使用.map以便正确呈现您的任务。您可以删除runArray并完全依赖props,因此无需在函数之间传递参数,因为它会很快变得混乱。这是一个快速运行的示例,说明如何创建一个父组件,您可以在其中添加任务并将它们传递到组件中,以便在更改道具时呈现数据,从而使其具有响应性。

class App extends React.Component {
  state = {
    taskLabel: "",
    tasks: [
      {
        id: 1,
        label: "Do something"
      },
      {
        id: 2,
        label: "Learn sometihng"
      }
    ]
  };

  handleInput = evt => {
    this.setState({
      [evt.target.name]: evt.target.value
    });
  };

  handleSubmit = evt => {
    evt.preventDefault();
    this.setState(prevState => ({
      taskLabel: "",
      tasks: [
        ...prevState.tasks,
        {
          id: prevState.tasks.length + 1,
          label: this.state.taskLabel
        }
      ]
    }));
  };

  render() {
    return (
      <div>
        <form onSubmit={this.handleSubmit}>
          <input
            name="taskLabel"
            type="text"
            placeholder="Task label"
            value={this.state.taskLabel}
            onChange={this.handleInput}
          />
          <button>Create task</button>
        </form>
        <DisplayCard tasks={this.state.tasks} />
      </div>
    );
  }
}

class DisplayCard extends React.Component {
  renderTasks = () => {
    if (this.props.tasks.length !== 0) {
      return this.props.tasks.map(task => (
        <div key={task.id}>{task.label}</div>
      ));
    } else {
      return <div>No tasks</div>;
    }
  };

  render() {
    return <div>{this.renderTasks()}</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"></div>