避免在 React 中由对象字面量引起的重新渲染:如何处理对象中的变量?
Posted
技术标签:
【中文标题】避免在 React 中由对象字面量引起的重新渲染:如何处理对象中的变量?【英文标题】:Avoid rerender in React caused by objects literal : how to do with variables in the object? 【发布时间】:2019-07-11 23:19:14 【问题描述】:我在这篇文章React is Slow, React is Fast: Optimizing React Apps in Practice 中读到:
实际上,每次将对象字面量作为 prop 传递给子组件时,都会破坏纯度。
好的,我知道了。所以最好避免这种情况是用对象创建一个变量,并将这个变量插入到道具中,就像这样:
import React from 'react';
const style = marginTop: 10 ;
const AnyComponent = (props) => (
<div style=style>
...
</div>
)
但是如果 style 属性依赖于接收到的属性呢?对象应该在哪里? 例如,我有这个组件:
import React from 'react';
const AnyComponent = (props) => (
<div style= marginTop: props.marginTop >
...
</div>
)
这是一个好习惯吗:
import React from 'react';
const style = (marginTop) => ( marginTop )
const AnyComponent = (props) => (
<div style=style(props.marginTop)>
...
</div>
)
[编辑] 我忘了说我的大多数组件都有状态,所以在这种情况下,这样做是个好主意吗:
import React from 'react';
class App extends React.Component
style = () => (
marginTop: this.props.marginTop
)
render()
return(
<div style=this.style()>
</div>
)
【问题讨论】:
你把事情复杂化了。您有性能问题吗? 我实际上是这样做的:我的应用程序非常大(比这大得多),使用 redux,并且我的一个深层嵌套组件使用了 Draft-js。为了方便起见,我想将 EditorState 存储在我的 redux 商店中,但由于性能和太多的重新渲染问题导致文本编辑器滞后,我现在不能这样做。我想试一试这个优化,因为我已经做了很多(重组、重新选择等) 【参考方案1】:以前您无法在函数式组件中执行此操作(尽管您可以使用 memoization) 但是现在借助 React 钩子,您可以执行以下操作:
const AnyComponent = (props) =>
const style = useMemo(() => ( marginTop: props.marginTop ), [props.marginTop]);
<div style=style>
...
</div>
不,你不能用这个:
import React from 'react';
const style = (marginTop) => ( marginTop )
const AnyComponent = (props) => (
<div style=style(props.marginTop)>
...
</div>
)
因为它还会在每次重新渲染 AnyComponent 时通过调用 style 函数创建一个新对象。
【讨论】:
useMemo
返回记忆值,而不是返回它的函数。 getStyle
的建议适用于 useCallback
。
@estus 非常感谢您的评论。我会编辑我的答案【参考方案2】:
您可以在组件中创建变量,如下所示:
import React from 'react';
const AnyComponent = (props) =>
// if props.marginTop is an object
const style = props.marginTop;
return (
<div style=style>
...
</div>
);
【讨论】:
这是不是每次都创建一个新的style
变量?之前的 style
和当前的 style
对象会有不同的地址,对吧?【参考方案3】:
一个对象可以用useMemo
钩子来记忆:
const AnyComponent = (( marginTop ) => (
const style = useMemo(() => ( marginTop ), [marginTop]);
<div style=style>
...
</div>
)
由于useMemo
旨在进行昂贵的计算并且有其自身的开销,因此对于div
情况,这可能被视为过早优化。
【讨论】:
感谢您的回复,您对类组件有什么建议?我用提案编辑了我的帖子,你怎么看?useMemo
特定于功能组件。你可以使用像 Lodash 这样的通用记忆器。正如我所提到的,这种优化对 没有多大意义。对于带有自定义 props 的类组件,更好的做法是让它们负责重新渲染决策,并使用 shouldComponentUpdate。
@estus 你能告诉它需要什么昂贵的计算吗?
@EddieCooro 一些占用大量 CPU 或 RAM 的函数,例如复杂对象对象。以上是关于避免在 React 中由对象字面量引起的重新渲染:如何处理对象中的变量?的主要内容,如果未能解决你的问题,请参考以下文章