繁体   English   中英

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

[英]Component Doesn't Update once the Parent component's state is updated

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> 我确实看到状态不断变化, this.props.saved不断变大,但是我的组件不再变化。

这是您的问题:

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()使用Array.map() ,它接受一个数组并转换每个元素,从而创建一个新数组:

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

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

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

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

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

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

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

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

它可以解决您的问题吗?

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

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)
  }
}

使用.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> 

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM