简体   繁体   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;

Hey guys, 大家好,

I am new to react, so this is my child component that takes state from its parent component. 我是个新手,所以这是我的子组件,它从其父组件获取状态。 My goal is to re-render component every time the array this.props.saved is changed. 我的目标是每次更改this.props.saved数组时都重新渲染组件。

This component renders: <p>You have no saved tasks.</p> when the this.props.saved.length === 0 and it renders <div>{array[0].task}</div> when i enter the first task, but it keeps it at <div>{array[0].task}</div> after that. 此组件呈现: <p>You have no saved tasks.</p>this.props.saved.length === 0 ,它呈现<div>{array[0].task}</div>输入第一个任务,但之后将其保留在<div>{array[0].task}</div> I do see that the state keeps changing and this.props.saved keeps getting bigger, but my component doesn't change anymore. 我确实看到状态不断变化, this.props.saved不断变大,但是我的组件不再变化。

Here's your problem: 这是您的问题:

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

This loop only ever goes through once (at i=0 ) and then returns, exiting the runArray function and cancelling the rest of the loop. 该循环仅执行一次(在i=0 ),然后返回,退出runArray函数并取消循环的其余部分。 You probably wanted to return an array of elements, one for each of the tasks. 您可能想返回一个元素数组,每个任务一个。 I recommend using Array.map() for this, which takes an array and transforms each element, creating a new array: 我建议Array.map()使用Array.map() ,它接受一个数组并转换每个元素,从而创建一个新数组:

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

This should do the trick. 这应该可以解决问题。 Note that React may complain about the fact that your elements lack the key property - see the documentation for more info: https://reactjs.org/docs/lists-and-keys.html 请注意,React可能会抱怨您的元素缺少key属性这一事实-有关更多信息,请参见文档: https : //reactjs.org/docs/lists-and-keys.html

The problem is in your runArray function. 问题出在您的runArray函数中。 Inside your loop, you are returning the first element and that's it. 在循环内部,您将返回第一个元素,仅此而已。 My guess is, you see only the first entry? 我的猜测是,您仅看到第一个条目?

When you are trying to render all your tasks, I would suggest to map your tasks, eg 当您尝试呈现所有任务时,建议您映射任务,例如

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

It is because you write wrong the runArray function. 这是因为您写错了runArray函数。 You make a return in the for loop so it breaks after the first iteration. 您在for循环中返回一个值,这样它在第一次迭代后就中断了。 It will not iterate over the full array. 它不会遍历整个数组。

You need to transform your for loop to a map : https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map 您需要将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>)
}

Does it fix your issue ? 它可以解决您的问题吗?

You have to update state of the component to trigger render function. 您必须更新组件的状态才能触发渲染功能。 Your render function is not triggered because you did not update the state when the props changed. 未触发渲染功能,因为在更改道具时未更新状态。 There are many ways to update state when props updated. 道具更新时,有多种更新状态的方法。 One method may be the following: 一种方法可能是以下方法:

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

Also change yoour render function to use state of the component as below: 同样更改您的渲染功能以使用组件的状态,如下所示:

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

Use .map so that it renders your task correctly. 使用.map,以便它正确呈现您的任务。 You can remove runArray and rely entirely on props so you don't need to pass arguments across functions as it can get messy quickly. 您可以删除runArray并完全依赖props,因此无需在函数之间传递参数,因为它会很快变得混乱。 Here's a quick running example of how to create a parent component where you can add a task and pass them into a component so that it renders your data when props are changed, therefore making it reactive. 这是一个快速运行的示例,说明如何创建一个父组件,您可以在其中添加任务并将它们传递到组件中,以便在更改道具时呈现数据,从而使其具有响应性。

 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