将反应虚拟化列表的当前索引设置为状态时发生错误
Error occurs when setting the current index of a react-virtualized List as state
问题
我正在尝试将 startIndex
置于 onRowsRendered()
内的状态。
这很好用,直到 CellMeasurer
被放入组合中。
向下滚动然后向上滚动时,出现以下错误:
Uncaught Invariant Violation: Maximum update depth exceeded. This can happen when a component repeatedly calls setState
inside componentWillUpdate
or componentDidUpdate
. React limits the number of nested updates to prevent infinite loops.
导致此问题的原因是什么?
演示
- with
CellMeasurer
(错误)
- without
CellMeasurer
(没有错误)
代码
import React from "react";
import ReactDOM from "react-dom";
import faker from "faker";
import { List, CellMeasurer, CellMeasurerCache } from "react-virtualized";
import "./styles.css";
faker.seed(1234);
const rows = [...Array(1000)].map(() =>
faker.lorem.sentence(faker.random.number({ min: 5, max: 10 }))
);
const App = () => {
const [currentIndex, setCurrentIndex] = React.useState(0);
const rowRenderer = ({ key, index, style, parent }) => {
return (
<div style={style}>
<div style={{ borderBottom: "1px solid #eee", padding: ".5em 0" }}>
{rows[index]}
</div>
</div>
);
};
return (
<>
<h1>{currentIndex}</h1>
<p>
<em>When scrolling down and then up, an error occurs. Why?</em>
</p>
<List
height={400}
width={600}
rowCount={rows.length}
rowHeight={35}
rowRenderer={rowRenderer}
style={{ outline: "none" }}
onRowsRendered={({ startIndex }) => {
setCurrentIndex(startIndex);
}}
/>
</>
);
};
const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);
您需要将 rowRenderer
和 cellMeasurer
函数移到功能组件之外。因为每次渲染功能组件时都会重新创建它。
功能组件:
https://codesandbox.io/s/nnp9z3o9wj?fontsize=14
或者你可以使用Class组件:
import React from "react";
import ReactDOM from "react-dom";
import faker from "faker";
import { List, CellMeasurer, CellMeasurerCache } from "react-virtualized";
import "./styles.css";
faker.seed(1234);
const rows = [...Array(1000)].map(() =>
faker.lorem.sentence(faker.random.number({ min: 5, max: 10 }))
);
class VirtualList extends React.Component {
rowRenderer = ({ key, index, style, parent }) => {
return (
<div style={style}>
<div style={{ borderBottom: "1px solid #eee", padding: ".5em 0" }}>
{rows[index]}
</div>
</div>
);
};
render() {
return (
<List
height={400}
width={600}
rowCount={rows.length}
rowHeight={35}
rowRenderer={this.rowRenderer}
style={{ outline: "none" }}
onRowsRendered={this.props.setCurrentIndex}
/>
)
}
}
const App = () => {
const [currentIndex, setCurrentIndex] = React.useState(0);
return (
<>
<h1>{currentIndex}</h1>
<p>
<em>When scrolling down and then up, an error occurs. Why?</em>
</p>
<VirtualList setCurrentIndex={setCurrentIndex} />
</>
);
};
问题
我正在尝试将 startIndex
置于 onRowsRendered()
内的状态。
这很好用,直到 CellMeasurer
被放入组合中。
向下滚动然后向上滚动时,出现以下错误:
Uncaught Invariant Violation: Maximum update depth exceeded. This can happen when a component repeatedly calls
setState
insidecomponentWillUpdate
orcomponentDidUpdate
. React limits the number of nested updates to prevent infinite loops.
导致此问题的原因是什么?
演示
- with
CellMeasurer
(错误) - without
CellMeasurer
(没有错误)
代码
import React from "react";
import ReactDOM from "react-dom";
import faker from "faker";
import { List, CellMeasurer, CellMeasurerCache } from "react-virtualized";
import "./styles.css";
faker.seed(1234);
const rows = [...Array(1000)].map(() =>
faker.lorem.sentence(faker.random.number({ min: 5, max: 10 }))
);
const App = () => {
const [currentIndex, setCurrentIndex] = React.useState(0);
const rowRenderer = ({ key, index, style, parent }) => {
return (
<div style={style}>
<div style={{ borderBottom: "1px solid #eee", padding: ".5em 0" }}>
{rows[index]}
</div>
</div>
);
};
return (
<>
<h1>{currentIndex}</h1>
<p>
<em>When scrolling down and then up, an error occurs. Why?</em>
</p>
<List
height={400}
width={600}
rowCount={rows.length}
rowHeight={35}
rowRenderer={rowRenderer}
style={{ outline: "none" }}
onRowsRendered={({ startIndex }) => {
setCurrentIndex(startIndex);
}}
/>
</>
);
};
const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);
您需要将 rowRenderer
和 cellMeasurer
函数移到功能组件之外。因为每次渲染功能组件时都会重新创建它。
功能组件: https://codesandbox.io/s/nnp9z3o9wj?fontsize=14
或者你可以使用Class组件:
import React from "react";
import ReactDOM from "react-dom";
import faker from "faker";
import { List, CellMeasurer, CellMeasurerCache } from "react-virtualized";
import "./styles.css";
faker.seed(1234);
const rows = [...Array(1000)].map(() =>
faker.lorem.sentence(faker.random.number({ min: 5, max: 10 }))
);
class VirtualList extends React.Component {
rowRenderer = ({ key, index, style, parent }) => {
return (
<div style={style}>
<div style={{ borderBottom: "1px solid #eee", padding: ".5em 0" }}>
{rows[index]}
</div>
</div>
);
};
render() {
return (
<List
height={400}
width={600}
rowCount={rows.length}
rowHeight={35}
rowRenderer={this.rowRenderer}
style={{ outline: "none" }}
onRowsRendered={this.props.setCurrentIndex}
/>
)
}
}
const App = () => {
const [currentIndex, setCurrentIndex] = React.useState(0);
return (
<>
<h1>{currentIndex}</h1>
<p>
<em>When scrolling down and then up, an error occurs. Why?</em>
</p>
<VirtualList setCurrentIndex={setCurrentIndex} />
</>
);
};