如何动态渲染组件列表,而又不每添加一个新组件就重新渲染整个列表?

时间:2019-07-23 12:30:54

标签: javascript reactjs react-redux

我想呈现与Redux存储中的某些对象具有1:1关系的组件列表。

我当前的代码是:

  props.images.forEach(imageFile => {
    let objectURL = URL.createObjectURL(imageFile);

    const newStyles = { 
      left: `${leftPosition}%`,
      top: `${topPosition}%`
    }

    previewFloats.push(
      <div className="Preview" style={{...style, ...newStyles}} key={v4()}></div>
    )
  });

  return(
    previewFloats
  )

编辑:示例(codesandbox.io/s/brave-mcnulty-0rrjz

问题在于,随着列表的增长,渲染整个背景图像列表的性能会受到很大的打击。

有什么更好的方法来实现这一目标?

编辑:仍然不确定为什么background-image src会触发重新渲染,但是建议使用<img>元素来使事情按预期进行。

3 个答案:

答案 0 :(得分:3)

Array.map()允许在React中动态渲染元素,这样只有那些更改道具的对象才能重新渲染(如the documentation中所述)。

如果您将使用此方法-而不是创建完整的数组并完全呈现它-React将仅重新呈现应该更新的元素:

props.images.map((imageFile, index) => {
    let objectURL = URL.createObjectURL(imageFile);

    const newStyles = { 
      left: `${leftPosition}%`,
      top: `${topPosition}%`
    }

    return (
      <div className="Preview" style={{...style, ...newStyles}} key={index}></div>
    )
});

请注意,我已经修改了数组中每个元素的key属性。它应该是唯一的,我不知道v4()是什么,所以我只使用了数组索引。
实际上,React的文档对此做了很好的解释:

  

键可帮助React识别哪些项目已更改,添加或删除

答案 1 :(得分:2)

您的答案是带有react组件的“键”属性。专为此类情况而设计 假设这是组件的一部分,则应具有以下内容:

return this.props.images.map(imageFile => (
    <div className="Preview" key={imageFile}></div>
))

假设imageFile是唯一的字符串。这种反应方式将重新渲染您的虚拟dom,但是它将认识到,对于具有相同键属性的相同元素,无需dom更新

答案 2 :(得分:0)

因此,感谢Github上的Dergash,我发现问题不在于我的列表被重新呈现。

因为我每次都在组件内部使用URL.createObjectURL创建一个新URL,并且因为'backgroundImage'不会进行图像预取,而src属性却能看到闪烁。

所以我的错误是没有先创建URL,然后再将其传递给组件。

工作示例:https://codesandbox.io/s/funny-http-8vrgv

更多详细信息:https://github.com/facebook/react/issues/16187