如何动态呈现组件列表,而无需在每次添加新内容时重新呈现整个列表



我想渲染一个与我的 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(

问题是,随着列表的增长,渲染整个背景图像列表的性能会受到相当大的影响。

实现这一目标

的更好方法是什么?

编辑:仍然不确定为什么背景图像 src 会触发重新渲染,但建议使用 <img> 元素代替让事情按预期工作。

Array.map()允许在 React 中动态渲染元素,因此只有那些更改其 props 的人才会重新渲染(如文档中所述(。

如果你使用这种方法 - 而不是创建完整的数组并完全渲染它 - 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 识别哪些项目已更改、添加或删除

你的答案是反应组件的"键"属性。它是为这种情况而构建的假设这是组件的渲染部分,您应该有这样的东西:

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

假设图像文件是唯一的字符串。通过这种方式,react 将重新渲染你的虚拟 dom,但它会认识到没有必要对具有相同键属性的相同元素进行 dom 更新

因此,多亏了 Github 上的 Dergash,我发现问题不在于我的列表被重新渲染。

因为我每次在我的组件中使用 URL.createObjectURL 创建一个新 URL,并且因为"backgroundImage"不进行图像预取,而 src 属性不进行闪烁。

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

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

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

最新更新