Added memoized-list-items sandbox

This commit is contained in:
Brian Vaughn
2018-09-03 09:27:55 -07:00
parent 8b53f06636
commit dfccc1f596
5 changed files with 130 additions and 23 deletions
@@ -0,0 +1,83 @@
import React, { PureComponent } from 'react';
import ReactDOM from 'react-dom';
import memoize from 'memoize-one';
import { FixedSizeList as List } from 'react-window';
const generateItems = numItems =>
Array(numItems)
.fill(true)
.map(_ => ({
isActive: false,
label: Math.random()
.toString(36)
.substr(2),
}));
// If list items are expensive to render,
// Consider using PureComponent to avoid unnecessary re-renders.
// https://reactjs.org/docs/react-api.html#reactpurecomponent
class ListItem extends PureComponent {
render() {
const { data, index, style } = this.props;
// Data passed to List as "itemData" is available as props.data
const { items, toggleItemActive } = data;
const item = items[index];
return (
<div onClick={() => toggleItemActive(index)} style={style}>
{item.label} is {item.isActive ? 'active' : 'inactive'}
</div>
);
}
}
// This helper function memoizes incoming props,
// To avoid causing unnecessary re-renders pure ListItem components.
// This is only needed since we are passing multiple props with a wrapper object.
// If we were only passing a single, stable value (e.g. items),
// We could just pass the value directly.
const getItemData = memoize((items, toggleItemActive) => ({
items,
toggleItemActive,
}));
class App extends PureComponent {
state = {
items: generateItems(1000),
};
toggleItemActive = index =>
this.setState(prevState => {
const item = prevState.items[index];
const items = prevState.items.concat();
items[index] = {
...item,
isActive: !item.isActive,
};
return { items };
});
render() {
const { items } = this.state;
// Bundle additional data to list items using the "itemData" prop.
// It will be accessible to item renderers as props.data.
// Memoize this data to avoid bypassing shouldComponentUpdate().
const itemData = getItemData(items, this.toggleItemActive);
return (
<List
height={150}
itemCount={items.length}
itemData={itemData}
itemSize={35}
width={300}
>
{ListItem}
</List>
);
}
}
ReactDOM.render(<App />, document.getElementById('root'));
@@ -0,0 +1,10 @@
{
"description": "Demo of react-window with advanced memoization techniques",
"main": "src/index.js",
"dependencies": {
"memoize-one": "^4",
"react": "^16",
"react-dom": "^16",
"react-window": "^1"
}
}
@@ -0,0 +1,19 @@
html {
font-family: sans-serif;
font-size: 12px;
}
.List {
border: 1px solid #d9dddd;
}
.ListItemEven,
.ListItemOdd {
display: flex;
align-items: center;
justify-content: center;
}
.ListItemEven {
background-color: #f8f8f0;
}
+9 -10
View File
@@ -44,27 +44,26 @@ class Example extends PureComponent {
toggleItemActive = index =>
this.setState(prevState => {
const item = prevState.items[index];
return {
items: {
...prevState.items,
[index]: {
...item,
isActive: !item.isActive,
},
},
const items = prevState.items.concat();
items[index] = {
...item,
isActive: !item.isActive,
};
return {items};
});
render() {
const { items } = this.state;
// Bundle additional data to list items using the "itemData" prop.
// It will be accessible to item renderers as props.data.
// Memoize this data to avoid bypassing shouldComponentUpdate().
const itemData = getItemData(this.state.items, this.toggleItemActive);
const itemData = getItemData(items, this.toggleItemActive);
return (
<List
height={height}
itemCount={listData.length}
itemCount={items.length}
itemData={itemData}
itemSize={35}
width={width}
@@ -8,8 +8,8 @@ import CODE from '../../code/MemoizedListItems.js';
import styles from './shared.module.css';
const generateItems = () =>
Array(1000)
const generateItems = numItems =>
Array(numItems)
.fill(true)
.map(_ => ({
isActive: false,
@@ -49,22 +49,18 @@ class ItemRenderer extends PureComponent {
export default class MemoizedListItemsExample extends PureComponent {
state = {
items: generateItems(),
items: generateItems(1000),
};
toggleItemActive = index =>
this.setState(prevState => {
const item = prevState.items[index];
return {
items: {
...prevState.items,
[index]: {
...item,
isActive: !item.isActive,
},
},
const items = prevState.items.concat();
items[index] = {
...item,
isActive: !item.isActive,
};
return { items };
});
render() {
@@ -82,7 +78,7 @@ export default class MemoizedListItemsExample extends PureComponent {
<FixedSizeList
className={styles.List}
height={150}
itemCount={1000}
itemCount={items.length}
itemData={itemData}
itemSize={35}
width={300}