Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
An example of ReactJS table that has sorting, pagination implemented using getDerivedStateFromProps
import React from "react";
import { render } from "react-dom";
import { MemoizedFlow } from "react-memoize";
const StatelessTable = ({ list, page, onPageChange, onSortChange }) => (
<table border={1} cellPadding={5}>
<thead>
<tr>
<th># counter</th>
<th>data from "list"</th>
<th>data from "extra"</th>
</tr>
</thead>
<tbody>
{list.map(({ id, extra }, index) => (
<tr>
<td>{index+page*10}</td>
<td>{id}</td>
<td>{extra}</td>
</tr>
))}
</tbody>
</table>
);
const genRandom = () =>
Array(100)
.fill(1)
.map(x => Math.round(1000 * Math.random()));
class Table extends React.Component {
state = {
page: 0,
sortOrder: 1,
extraData: [],
extraSorting: true,
random: 0,
seedAddition: 0
};
sideEffect = () => Promise.resolve().then(this.setState({ extraData: genRandom() }));
render() {
return (
<div>
This table is "flow" memoized
<MemoizedFlow
input={{ ...this.state, ...this.props }}
flow={[
// could change list!
({ list, seedAddition }) => ({ list: list.map(id => + id + Math.round(10*Math.random()))}),
// side effect, react only on `random` change
({ random }) => this.sideEffect(random),
// map list numbers to object
({ list }) => ({
list: list.map((line, index) => ({
id: line
}))
}),
// mix with extra data from sideEffect BEFORE Sorting
({ list, extraData, extraSorting }) => extraSorting && ({
list: list.map((line, index) => ({
...line,
extra: extraData[index]
}))
}),
// sorting, react on data or sort order change
({ list, sortOrder }) => ({
list: list.slice().sort((a, b) => sortOrder * (a.id - b.id))
}),
// mix with extra data from sideEffect AFTER sorting
({ list, extraData, extraSorting }) => !extraSorting && ({
list: list.map((line, index) => ({
...line,
extra: extraData[index]
}))
}),
// pagination
({ list, page }) => ({ list: list.slice(page*10, page*10+10) }),
]}
>
{({ list, page }) => (
<StatelessTable
list={list}
page={page}
onPageChange={this.onPageChange}
/>
)}
</MemoizedFlow>
<br />
<br />
changePage:
<select onChange={event => this.setState({ page: event.target.value})}>
{ Array(this.props.list.length/10).fill(1).map((i, index)=>(
<option value={index}>{index+1}</option>
))}
</select> and it will be applied without list regeneration
<br /><br />
<button onClick={() => this.setState(state => ({ seedAddition: state.seedAddition + 1 }))}>Randomize</button>
only ONLY it will update EVERYTHING.
<br /><br />
<button onClick={() => this.setState(state=>({random: state.random+1}))}>Apply side effect</button> to update extra
<br /><br />
<button onClick={() => this.setState(state => ({ extraSorting: !state.extraSorting }))}>Flip extra sorting</button> to make extra applied before or after sorting
<br /><br />
<button onClick={() => this.setState(state => ({ sortOrder: -state.sortOrder }))}>Flip sorting</button> just to change sort order
<br /><br />
<button onClick={() => this.setState(state => ({ seedAddition: state.seedAddition + 1 }))}>Randomize</button>
only ONLY it will update EVERYTHING (keep in mind - data is sorted).
</div>
);
}
}
const randomData = genRandom();
const App = () => (
<div>
<Table list={randomData} />
</div>
);
render(<App />, document.getElementById("root"));
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment