这是一个复杂的问题。希望我设法解释,以便每个人都能理解错误
1) 父组件。
@observer
export class Edit extends React.Component<IProps> {
article: any
componentWillMount() {
const articleId = this.props.routerStore!.routerState.params.id!
this.article = ArticleModel.create({ id: articleId || null })
this.article.init()
}
render() {
if (!this.article) {
return <div>loading...</div>
}
return <div className='main-wrapper'>
<EditArticle article={this.article} />
</div>
}
}
2)子组件
它使用react-beautiful-dnd
允许在文章布局上拖放。这个库使用 RenderProps(provided: any, snapshot)
@observer
export class EditArticle extends React.Component<IProps> {
render() {
return <div className='main-column article-target'>
<Droppable
ignoreContainerClipping
direction={'vertical'}
droppableId='article'
key={'article'}
>
{(provided: any, snapshot: any) => {
return <ObservedDragDropContext
provided={provided}
snapshot={snapshot}
>
{this.props.article.layout.map((el: any, index: number) => {
return <WithDragable
key={getPath(el)}
id={getPath(el)}
index={index}
remove={() => {}}
>
<div className='layout-item'>
<Layout key={getPath(el)} item={el} />
</div>
</WithDragable>
})}
</ObservedDragDropContext>
}}
</Droppable>
</div>
}
}
文章是一个 mobx-state-tree 模型。这是模型的 actions 属性的 init 方法:
init() {
const run = flow(function*() {
const res = yield getArticle(self.id)
applySnapshot(self, res)
})
run()
},
流程如下: 1) 创建文章 2) 初始化文章 3) 我希望在我得到响应并在文章上应用快照后看到文章更新
但是运行 applySnapshot 后子组件不会重新渲染。我检查并运行了 applySnapshot,并且文章具有从后端收到的更新值。
我认为问题是因为我在子组件中使用了 RenderProps,这会以某种方式干扰并限制组件重新渲染。
棘手的一点是,如果我添加
{this.props.article.layout.map((el: any, index: number) =>
<Layout key={getPath(el)} item={el} />
)}
在render
函数的任何地方的子组件中,这将解决问题并更新初始组件。因此,只需重新渲染道具,子组件就会重新渲染自身,并通过重新渲染 Drappable 和 RenderProps 隐式修复我的初始错误。
可能的解决方案 1:如果我使用不使用 RenderProps 的不同反应 DND 库,则所有内容都会按应有的方式更新。但我不想这样做,因为react-beautiful-dnd
它有很好的动画,我需要重构一些代码。
我无法理解为什么不重新渲染 Child 组件。
子组件是否不知道它依赖于文章,因为我只使用this.props.article
了 renderProps 内部?
我可以避免使用 renderProps 吗?