![](/img/trans.png)
[英]Child component doesn't update correctly with state update in parent component
[英]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.