Created
November 16, 2017 20:19
-
-
Save blainekasten/b2b6df29a5cea2a0959a6813f3aa0d3b to your computer and use it in GitHub Desktop.
RenderProps vs HOC
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// This Component fetches data from a server and then renders its children. | |
// Important to remember that any time the parent component re-renders, this component re-renders also. | |
// I think the main difference is this version makes the fetching a Child while the HOC makes the fetching a Parent. | |
export class GetDataList extends Component { | |
props: { children: Function } | |
state = { dataList: null }; | |
componentDidMount() { | |
// assume this is 1000s of records. Unpaginated so we can client side sort. | |
asyncFetchLargeDataList().then(dataList => this.setState({dataList})) | |
} | |
render() { | |
const { dataList, children: renderProp } = this.state; | |
return dataList ? renderProp(dataList) : null; | |
} | |
} | |
// Parent Component version. | |
export withDataList = (Comp) => <GetDataList>{dataList => <Comp dataList={dataList} />}</GetDataList>; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { withDataList } from 'get-data-list'; | |
export default class PerformantChild extends Component { | |
props: { dataList: Array<Object> } | |
constructor(props) { | |
super(props); | |
this.state = { | |
sort: 'asc', | |
dataList: this.computePropsAndSort(props.dataList), | |
} | |
} | |
componentWillReceiveProps(props) { | |
if (props.dataList !== this.props.dataList) { | |
this.setState({ | |
dataList: this.computePropsAndSort(props.dataList) | |
}); | |
} | |
} | |
computePropsAndSort(dataList) { | |
return dataList | |
.sort((a, b) => this.state.sort === 'asc' | |
? a.order < b.order | |
: a.order > b.order | |
) | |
.map((data => ({ | |
...data, | |
computedProp: data.status === 0 & data.isFunctional ? 'Enabled' : 'Disabled', | |
}); | |
} | |
switchSort = () => { | |
this.setState({ sort: this.state.sort === 'asc' ? 'desc' : 'asc' }); | |
} | |
render() { | |
// Now rendering is cheap. Zero manipulation at render time. | |
return ( | |
<div> | |
<div onClick={this.switchSort}>Functionality</div> | |
{this.state.dataList | |
.map(sortedList => (<div>{sortedList.computedProp}</div>))} | |
</div> | |
); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { GetDataList } from 'get-data-list'; | |
export default class UnperformantParent extends Component { | |
state = { sort: 'asc' } | |
switchSort = () => { | |
this.setState({ sort: this.state.sort === 'asc' ? 'desc' : 'asc' }); | |
} | |
computePropsAndSort(dataList) { | |
return dataList | |
.sort((a, b) => this.state.sort === 'asc' | |
? a.order < b.order | |
: a.order > b.order | |
) | |
.map((data => ({ | |
...data, | |
computedProp: data.status === 0 & data.isFunctional ? 'Enabled' : 'Disabled', | |
}); | |
} | |
render() { | |
// Note that every time the header (Functionality) is clicked, the component is re-rendered. Which means the renderProp | |
// will give us back the same pure data, unsorted, uncomputed, and we'll have to do that again. | |
// Being a child of this component forces us into this position where we can't save the `dataList` in this component. | |
return ( | |
<div> | |
<div onClick={this.switchSort}>Functionality</div> | |
<GetDataList> | |
{dataList => this | |
.computePropsAndSort(dataList) | |
.map(sortedList => (<div>{sortedList.computedProp}</div>)) | |
} | |
</GetDataList> | |
</div> | |
); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment