我正在开发一个最近才开始使用React(替换d3)的应用程序。它大致沿着MVC范例构建,其中React仅用于(部分)视图,因此没有一些根状态React组件,其状态控制着一切。实际上,几乎所有的React组件都是无状态的(只有少数组件具有较小的内部状态,用于处理不需要更新模型的内容)。
因此,我们不是让根组件具有控制状态,而是让React组件通过回调报告操作,最终更新模型并触发重新呈现视图。在ReactDom.render(<SomeComponent {...props} />, someElement);
中,基于新的更新模型创建了props
。并非视图中的所有内容都使用React(尽管我们正朝着这个目标努力),而且并非每个React组件都包含在任何单个根React组件中(如果没有其他原因,我们的应用程序有时会使用多个组件)浏览器窗口)。
在这种情况下,使用新道具再次调用ReactDom.render
是否正确更新我们的React视图?这对我们来说似乎很令人惊讶,但它似乎是我们在文档等中阅读的内容。它似乎确实有效。但今天我添加了对ReactDom.render
的新调用,现在我们在控制台中收到此警告:
警告:render(...):用新的根组件替换React渲染的子组件。如果您打算更新此节点的子节点,则应该让现有子节点更新其状态并呈现新组件,而不是调用ReactDOM.render。
我们只是通过新的ReactDom.render
电话获得此信息;许多其他人在此之前没有给我们这个警告。事实上,触发此警告的代码非常类似:
// selection is a d3 selection that has not been converted to React yet
// data includes the updated data for this object and its children
selection.each(function (data) {
const someElement = d3.select(this).select('.some-class').node();
ReactDom.render(
<>
{data.someChildren
.map(toSomeProps)
.map(someProps =>
<SomeComponent key={keyOf(someProps)} {...someProps} />
)
}
</>,
someElement
);
const anotherElement = d3.select(this).select('.another-class').node();
const anotherProps = toAnotherProps(data);
ReactDom.render(
<AnotherComponent {...anotherProps} />,
anotherElement
);
});
(对于那些不熟悉d3的人来说,这实际上是采用一系列元素,在其中查找特定的子元素,并在这些子元素中渲染React组件。最终,这将被迁移到React。)
SomeComponent
s组是新组,AnotherComponent
已经存在。我收到关于SomeComponent
的警告,但没有关于AnotherComponent
的警告。也许它不会重复两个彼此相邻的警告,但是当AnotherComponent
是那里唯一的部分时,我们从未收到警告。
我在这里唯一值得注意的差异是在<>{...}</>
案例中使用SomeComponent
,而不是“真正的”包装组件。那有关系吗?如果是这样,为什么?