反应父组件不重新渲染
Posted
技术标签:
【中文标题】反应父组件不重新渲染【英文标题】:React Parent Component not re-rendering 【发布时间】:2018-09-19 03:10:01 【问题描述】:我有一个父组件,它呈现从 API 中提取的子列表(功能正确)。每个孩子都可以选择删除自己。当孩子删除自己时,我无法让父母重新渲染。我在这里阅读了与该主题相关的大约 50 个答案,并尝试了所有这些答案,但似乎没有任何效果。我错过了一些东西并卡住了。
组件已经连接了 redux,但我已经尝试了连接和不连接 redux 的代码。我也在回调中尝试了 this.forceUpdate() ,它也不起作用(我在下面的示例代码中将其注释掉了)。
class Parent extends React.Component
constructor(props)
super(props)
this.refresh = this.refresh.bind(this)
this.state =
refresh: false,
componentDidMount()
this.getChildren()
refresh = () =>
console.log("State: ", this.state)
this.setState( refresh: !this.state.refresh )
// this.forceUpdate();
console.log("new state: ", this.state)
getChildren = () =>
axios.get(
config.api_url + `/api/children?page=$this.state.page`,
headers: token: ls('token')
).then(resp =>
this.setState(
children: this.state.children.concat(resp.data.children)
)
)
render()
return (
<div>
_.map(this.state.children, (chidlren,i) =>
<Children
key=i
children=children
refresh=() => this.refresh()
/>
)
</div>
)
然后在我的 Children 组件中,它工作得很好,并且删除按钮成功地从数据库中删除了记录,我有以下摘录:
deleteChild = (e) =>
e.preventDefault();
axios.delete(
config.api_url + `/api/children/$this.state.child.id`,
headers: token: ls('token')
).then(resp =>
console.log("The response is: ", resp);
)
this.props.refresh();
render()
return(
<button class="btn" onClick=this.deleteChild>Delete</button>
)
我确定我遗漏了一些简单或基本的东西,但我找不到。
【问题讨论】:
我应该补充一点,父组件状态确实发生了变化(即使第一个 console.log 没有反映它的异步性质,它正在改变,因为我在 Parent 中添加了一个按钮测试它),即使父状态发生变化,我删除的孩子也没有消失/父母没有重新渲染。 您可能希望将this.props.refresh();
移动到axios
调用的then
处理程序中。
【参考方案1】:
您的父渲染方法仅取决于 this.state.children,它在您的删除事件中没有改变。将子 ID 传递给您的 this.props.refresh 方法,例如 this.props.refresh(this.state.child.id) 并在刷新方法中更新 this.state.children 或在删除后再次调用 get children 方法发生了
子进程中删除方法的代码
this.props.refresh(this.state.child.id)
父刷新方法代码
refresh = (childIdToBeDeleted) =>
console.log("State: ", this.state)
this.setState( refresh: !this.state.refresh )
// this.forceUpdate();
console.log("new state: ", this.state)
//New code
this.setState(children: this.state.children.filter(child => child.id !== childIdToBeDeleted);
【讨论】:
谢谢 - 这就像一个魅力(我将删除函数从子函数移到父函数作为回调,使用 id 作为参数,然后按照你的建议过滤状态)。现在代码也变得更好、更简洁了!【参考方案2】:关于代码的一些注释。首先从 db 中删除然后重新加载可能会很慢并且不是最佳解决方案。或许可以考虑添加remove()
函数,该函数可以传递给子组件以更快地更新状态。
其次,如果你想调用setState
,这取决于之前的状态,最好使用这样的回调方法(但我认为你需要其他东西见下文)
this.setState((prevState,prevProps) =>
children: prevState.children.concat(resp.data.children))
最后,我认为问题是什么。你实际上并没有从refresh
方法调用getChildren
,所以状态没有更新,如果你想从数据库重新加载整个状态,你不应该连接,而是像这样设置它
.then(resp =>
this.setState(children: resp.data.children)
希望对你有帮助。
编辑:
正如 cmets 中提到的,孩子们对refresh
的调用应该是承诺then
【讨论】:
谢谢 - 去看看。顺便说一句,chidlren 只是我的 *** 代码中的一个错字 - 真正的代码没有这个以上是关于反应父组件不重新渲染的主要内容,如果未能解决你的问题,请参考以下文章
防止子级在更新父级状态时重新渲染,使用父级方法作为本机反应的道具