簡體   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