在 React 应用中映射数组以优化性能的最佳实践
Posted
技术标签:
【中文标题】在 React 应用中映射数组以优化性能的最佳实践【英文标题】:Best practice for mapping an array in React app for performance optimization 【发布时间】:2019-01-21 17:47:50 【问题描述】:我正在制作一个返回搜索结果的简单字典应用程序。使用字典的内存数据库lokiJS 对搜索字段的每个onChange
进行查询,因此结果非常很快。
优化结果的呈现对我来说很重要,这样大约 50 个过滤后的搜索结果会随着用户键入和每次击键时发生的查询而持续流动。
这是我到目前为止一直在做的事情:(这可行,但它是最好/最快的方法吗?)
数据库的每个(同步)查询都返回一个对象数组,然后我将其映射为如下所示:
queryDB(query)
const results = queryLokiJsDB(query);
const resultsMapped = results.map((mpd) =>
<dl key=mpd["$loki"] onClick=() => this.clickFunction(mpd.p, mpd.f)>
<dt>mpd.p - mpd.f</dt> <dd>mpd.e <em>mpd.c</em></dd>
</dl>);
this.setState( results: (
<div>
resultsMapped
</div>
));
然后,一旦我有这样映射的结果,我将映射的组件添加到状态,然后屏幕会用新的结果呈现。
render()
return (
<div>
<SearchBarStuff />
<div className="results-container">
this.state.results
</div>
</div>
);
我在学习 React 的时候做了这个,我知道人们认为将组件存储在状态中是 非常糟糕的做法。
我想知道在性能优化(和代码清洁度)方面的最佳实践是什么。 我应该将结果数组存储在 state 中然后渲染然后将它们映射到渲染函数中的组件中吗?这会导致性能下降吗?
Another answer 表示“每次渲染都会创建一个 render 方法中的函数,这对性能有轻微影响。”
为什么在状态中存储组件如此糟糕?仅仅是为了代码清晰吗?保持国家小?感谢您的帮助和耐心。
【问题讨论】:
如果我猜的话,我认为将组件存储在 state 中是不好的做法,因为 React 必须将以前的 state 与新 state 进行比较,看看它是否需要重新渲染,如果它有要爬过如此庞大的组件数组而不是对象数组,您正在让它做更多的工作。最好的做法是将对象数组存储在 state 中,然后在组件中处理它们的映射和渲染。 @larz 但是 React 文档说它以浅层的方式比较状态,这意味着对于对象,它只会检查引用是否发生了变化。在 OP 的示例中,每次调用setState(results)
时,React 都会立即看到 results
已更改,因为新组件实例将是不同的对象引用。因此,我会说这种情况下的性能不会受到影响。
【参考方案1】:
我不太确定,但我想的问题与 @larz 在 cmets 中解释的问题相同。另外,正如您提到的,状态会更清晰。所以在这里,如果我是你,我会怎么做。
首先,用结果来设置你的状态:
queryDB(query)
const results = queryLokiJsDB(query);
this.setState( results );
然后,映射结果,但我不会立即创建 JSX,而是使用单独的组件。将 mpd
(元素)和 onClick
函数及其引用传递给它。
render()
return (
<div>
<SearchBarStuff />
<div className="results-container">
this.state.results.map( mpd => (
<Item key=mpd["$loki"] mpd=mpd onClick=this.clickFunction />
) )
</div>
</div>
);
像这样使用Item
:
const Item = ( props ) =>
const mpd, onClick = props;
const handleClick = () => onClick( mpd.p, mpd.f );
return (
<dl onClick=handleClick>
<dt>mpd.p - mpd.f</dt> <dd>mpd.e <em>mpd.c</em></dd>
</dl>
);
这样,您不会在 onClick
处理程序中使用箭头函数,因此由于我们使用引用,因此不会在每次渲染中重新创建此函数。
【讨论】:
嗯...这对我来说实际上似乎让事情变慢了一点。也许我的问题是我需要将每个项目的参数传递给 click 函数,所以它必须看起来像这样:onClick=() => this.clickFunction(mpd.foo, mpd.bar)
。所以我仍然需要在我的 onClick 处理程序中使用箭头函数。 (因为onClick=this.clickFunction(mpd.foo, mpd.bar)
会在渲染时执行。:-( 有什么想法吗?
您如何决定这种方式会减慢速度?不要误解我,我只是想了解问题。你的意思是说写这么多代码变慢?如果需要,无需单独的组件,您可以使用此处描述的箭头功能。但是,通过这种方式,该函数将在每次渲染中重新创建。我不知道这对性能有多大影响。有人说多,有人说少。
不,我的意思是在 chrome 开发人员工具的性能选项卡中查看、编写脚本和渲染时间。但是今天我尝试进行更多重构,您建议的方式现在比我以前的设置运行得更快。 (当我第一次尝试时,您的方式似乎慢了 20-30%,但我可能做错了其他事情。)谢谢您的帮助。我认为您的方式在代码清洁度和可扩展性方面更好,即使它只是快一点。
不客气。是的,在 React 世界中,分离组件是一种建议的方式。即使在我的示例中 render
方法有点拥挤 :) .map
可以使用单独的方法。很高兴你解决了它。以上是关于在 React 应用中映射数组以优化性能的最佳实践的主要内容,如果未能解决你的问题,请参考以下文章