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