简体   繁体   中英

List component continually re-renders

I feel like this is likely due to me not understanding the flow of React, but I've been struggling to figure it out. Have an infinite scroll list.

if Row is outside of Scroller it works fine.

However, if Row is inside of Scroller , it results in the component constantly re-rendering. I was hoping to pass a list into Scroller from the parent component with around a thousand items, but in order to do that, I need Row in Scroller to be able to access the props. Whats the best way to go about this?

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;


I'm not 100% sure what you're asking, but I think I have an idea...

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 for more information regarding passing in data to List and accessing data from within the child function.

Here's a working demo:

编辑虚拟窗口自定义数据

By design, this child function is supposed to be re-rendered to add/remove items from the DOM as the user scrolls up/down. To view this behavior, right click on an element, like Season Id , within in the codesandbox window and click on "Inspect" -- you may need to do this twice to focus on the targeted element -- then while the mouse is hovered over the codesandbox render window, scroll down. What you'll notice is that items are dynamically added/removed based upon the scroll direction. So if you're expecting this child function to NOT be re-rendered when the window is scrolled, then you probably shouldn't be using a virtualized list and, instead, should be using pagination.


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"));

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM