反应:如何将当前的道具儿童与新道具儿童进行比较
React: how to compare current props.children with new one
嗨,
我正在构建一个组件,它只充当其他生成内容的包装器,并使用第三方库。该库与组件的props.children
配合使用。到目前为止还不错,但这个第三方库在应用或刷新元素时有点滞后。因为刷新这个库的唯一原因是当props.children
发生变化时,我正在尝试如何比较shouldComponentUpdate
中的this.props.children
和nextProps.children
。我想PureRenderMixin应该做这项工作,但对我来说,它不起作用。即使我只更改state.listName
,也会重新绘制组件,如下例所示。
<div>
List name '{this.state.listName}'
<br />
<MyComponent>
<ul>
{listOfLi}
</ul>
</MyComponent>
</div>
有没有任何方法,如何管理props.children
的比较或任何其他选项,如何做类似的事情?谢谢你的帮助!
正如Matt S所指出的,可接受的答案是一种脆弱的解决方法,取决于key
的非标准使用。除了他列出的列表示例之外,如果您的id
保持不变,但它们所代表的资源中的某些字段被修改,那么即使使用类似key={id}
的东西也会失败。
本期包含了关于该主题的良好讨论,并以更稳定的解决方法结束。从本质上讲,您可以简化children
道具,使其能够运行深度比较。您可以使用React.Children
实用程序来编写简化方法:
// Flattens all child elements into a single list
const flatten = (children, flat = []) => {
flat = [ ...flat, ...React.Children.toArray(children) ]
if (children.props && children.props.children) {
return flatten(children.props.children, flat)
}
return flat
}
// Strips all circular references and internal fields
const simplify = children => {
const flat = flatten(children)
return flat.map(
({
key,
ref,
type,
props: {
children,
...props
}
}) => ({
key, ref, type, props
})
)
}
然后可以使用shouldComponentUpdate
或React.memo
来防止重新渲染:
const MyComponent = ({ children }) => (
<div>{ children }</div>
)
export default React.memo(MyComponent, (prev, next) => (
JSON.stringify(simplify(prev.children)) ===
JSON.stringify(simplify(next.children))
))
这些实用程序+JSON.stringify
只是一种方法,注释中提到的方法类似,您也可以利用lodash.isequal
等实用程序进行深入比较。不幸的是,我不知道有哪一两句话可以进行比较,但如果你知道一种更简单稳定的方法,请评论!
您可以使用子key
道具,React建议应该给子数组以唯一标识它们。因为每个子对象都有一个密钥,所以可以可靠地判断子对象是否在道具更改中发生了更改(这就是密钥的全部意义!)。如果新钥匙和旧钥匙不匹配,那么它们就变了。
React.render(<App><Child key='1'/><Child key='2'/></App>, document.body)
如果孩子们更改了,请在每次更新前检查你想要检查的应用程序组件
shouldComponentUpdate(nextProps){
var oldKeys = this.props.children.map( child => child.key);
var newKeys = nextProps.children.map( child => child.key);
//compare new and old keys to make sure they are the same
}
注意,这并不能告诉你每个孩子的内容是否发生了变化,如果你想知道这一点下的整棵树中是否没有任何东西改变,你必须根据一些标准对每个孩子进行比较(例如深入比较道具)
作为进一步的优化,我们知道孩子永远不会因为状态变化而改变,所以我们实际上可以在componentWillReceiveProps()
中进行比较,只需设置一些状态属性,如childrenHaveChanged
您所描述的设计和行为有些问题。您应该很少(如果有的话)关心执行children
的手动diff。这应该留给React。如果每次组件更新时,无论是因为children
还是其他状态/属性更改,您使用的库都会阻塞,那么它不是被动编写的,您应该寻找一个不同的被动编写的库。或者,您可以通过打开问题或提交拉取请求来帮助修复开源项目中的这种行为。
做你想做的事情并不容易,因为这不应该是必要的。React非常非常擅长处理对账,并且只有在实际发生变化时才会呈现,这将改变与其相关的DOM的状态。
- underline-js:将键对象与数组键对象进行比较,如果存在,则移除现有的添加新的
- 为什么shouldComponentUpdate说当前道具是React中的新道具
- 反应:如何将当前的道具儿童与新道具儿童进行比较
- 在获取后将新模型准备到集合中(不带比较器)
- React选择性地不将新道具传递给渲染对象
- 主干中的比较器在添加新模型时需要排序调用
- 比较新旧变量的角度
- React Native接收新道具,componentWillReceiveProps
- ReactJS:比较shouldComponentUpdate上的道具和状态
- 比较两个数组,并通过使用 javascript 保留现有对象来更新新值
- 如何比较具有相同值的两个数组并将该相同值存储在新数组中
- 比较两个JSON数组并重新排列新的JSON数组格式
- 使用 JavaScript 比较 2 个数组并创建一个新的对象数组,该数组不包含与 id 字段匹配的对象
- 在运行之前确定数据是否是新的(将数组与 JSON 进行比较)
- 比较两个数组并返回一个新数组,其中包含仅在其中一个原始数组中找到的任何项目
- 在比较字符串的字符后创建新数组&大堆
- 需要将新日期与日期选择器进行比较
- 使用数组循环将值与另一个电子表格进行比较,然后写入新值
- 如何在React 0.14中使用新道具在顶层再次渲染组件
- 当使用新道具调用渲染时,React JS没有完全更新视图