Skip to content

Instantly share code, notes, and snippets.

@sunpietro
Created April 24, 2018 09:00
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save sunpietro/8c7a2681f4da445bb7c7de75a6ef8333 to your computer and use it in GitHub Desktop.
Save sunpietro/8c7a2681f4da445bb7c7de75a6ef8333 to your computer and use it in GitHub Desktop.
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