列表组件不断重新渲染
List component continually re-renders
我觉得这可能是因为我不了解 React 的流程,但我一直在努力弄清楚。有一个无限滚动列表。
如果 Row
在 Scroller
之外,它工作正常。
但是,如果 Row
在 Scroller
内部,则会导致组件不断重新渲染。我希望将包含大约一千个项目的父组件的列表传递到 Scroller
,但为了做到这一点,我需要 Scroller
中的 Row
才能访问道具.解决此问题的最佳方法是什么?
import React from "react";
import { FixedSizeList as List } from "react-window";
import AutoSizer from "react-virtualized-auto-sizer";
const Scroller = (randomArray) => {
const Row = ({ index, style }) => (
<div className={index % 2 ? "ListItemOdd" : "ListItemEven"} style={style}>
{randomArray[index]}
</div>
);
return (
<AutoSizer>
{({ height, width }) => (
<List
className="List"
height={height}
itemCount={1000}
itemSize={35}
width={width}
>
{Row}
</List>
)}
</AutoSizer>
);
};
export default Scroller;
我不是 100% 确定你在问什么,但我想我有一个想法...
Render props can be a bit confusing, but they're essentially children
components that are functions. Meaning, the direct child of List
must be a function that accepts an object of parameters and returns JSX. See this react-window gist 有关将数据传递到 List
和从子函数内部访问 data
的更多信息。
这是一个工作演示:
根据设计,当用户滚动 up/down 时,该子函数应该重新呈现到 DOM 中的 add/remove 项。要查看此行为,请右键单击代码框 window 中的一个元素,例如 Season Id
,然后单击“检查”——您可能需要执行此操作两次以关注目标元素——然后当鼠标悬停在 codesandbox render window 上时,向下滚动。您会注意到,项目是根据滚动方向动态 added/removed 的。因此,如果您希望在 window 滚动时不会重新呈现此子函数,那么您可能不应该使用虚拟化列表,而应该使用分页。
Example.js
import React from "react";
import { FixedSizeList as List } from "react-window";
import AutoSizer from "react-virtualized-auto-sizer";
const Example = ({ dataList }) => (
<AutoSizer>
{({ height, width }) => (
<List
className="List"
height={height}
itemCount={dataList.length}
itemData={dataList}
itemSize={265}
width={width}
>
{({ data, index, style }) => {
const dataItem = data[index];
return (
<div
className={index % 2 ? "ListItemOdd" : "ListItemEven"}
style={style}
>
<h1>Season Id: {dataItem.seasonId}</h1>
<h2>Form Id: {dataItem._id}</h2>
<h2>Start Month: {dataItem.startMonth}</h2>
<h2>End Month: {dataItem.endMonth}</h2>
<h2>Send Reminders: {dataItem.sentReminders.toString()}</h2>
</div>
);
}}
</List>
)}
</AutoSizer>
);
export default Example;
index.js
import React from "react";
import { render } from "react-dom";
import Example from "./Example";
import dataList from "./data.json";
import "./styles.css";
render(<Example dataList={dataList} />, document.getElementById("root"));
我觉得这可能是因为我不了解 React 的流程,但我一直在努力弄清楚。有一个无限滚动列表。
如果 Row
在 Scroller
之外,它工作正常。
但是,如果 Row
在 Scroller
内部,则会导致组件不断重新渲染。我希望将包含大约一千个项目的父组件的列表传递到 Scroller
,但为了做到这一点,我需要 Scroller
中的 Row
才能访问道具.解决此问题的最佳方法是什么?
import React from "react";
import { FixedSizeList as List } from "react-window";
import AutoSizer from "react-virtualized-auto-sizer";
const Scroller = (randomArray) => {
const Row = ({ index, style }) => (
<div className={index % 2 ? "ListItemOdd" : "ListItemEven"} style={style}>
{randomArray[index]}
</div>
);
return (
<AutoSizer>
{({ height, width }) => (
<List
className="List"
height={height}
itemCount={1000}
itemSize={35}
width={width}
>
{Row}
</List>
)}
</AutoSizer>
);
};
export default Scroller;
我不是 100% 确定你在问什么,但我想我有一个想法...
Render props can be a bit confusing, but they're essentially children
components that are functions. Meaning, the direct child of List
must be a function that accepts an object of parameters and returns JSX. See this react-window gist 有关将数据传递到 List
和从子函数内部访问 data
的更多信息。
这是一个工作演示:
根据设计,当用户滚动 up/down 时,该子函数应该重新呈现到 DOM 中的 add/remove 项。要查看此行为,请右键单击代码框 window 中的一个元素,例如 Season Id
,然后单击“检查”——您可能需要执行此操作两次以关注目标元素——然后当鼠标悬停在 codesandbox render window 上时,向下滚动。您会注意到,项目是根据滚动方向动态 added/removed 的。因此,如果您希望在 window 滚动时不会重新呈现此子函数,那么您可能不应该使用虚拟化列表,而应该使用分页。
Example.js
import React from "react";
import { FixedSizeList as List } from "react-window";
import AutoSizer from "react-virtualized-auto-sizer";
const Example = ({ dataList }) => (
<AutoSizer>
{({ height, width }) => (
<List
className="List"
height={height}
itemCount={dataList.length}
itemData={dataList}
itemSize={265}
width={width}
>
{({ data, index, style }) => {
const dataItem = data[index];
return (
<div
className={index % 2 ? "ListItemOdd" : "ListItemEven"}
style={style}
>
<h1>Season Id: {dataItem.seasonId}</h1>
<h2>Form Id: {dataItem._id}</h2>
<h2>Start Month: {dataItem.startMonth}</h2>
<h2>End Month: {dataItem.endMonth}</h2>
<h2>Send Reminders: {dataItem.sentReminders.toString()}</h2>
</div>
);
}}
</List>
)}
</AutoSizer>
);
export default Example;
index.js
import React from "react";
import { render } from "react-dom";
import Example from "./Example";
import dataList from "./data.json";
import "./styles.css";
render(<Example dataList={dataList} />, document.getElementById("root"));