Created
December 19, 2018 21:00
-
-
Save pmg103/817cea61a850c3a5879488fc51d61e8c to your computer and use it in GitHub Desktop.
Use render props to isolate loading/collection from component
This file contains hidden or 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
const ActivityEdit = ({activity, updateActivity, response}) => ( | |
<div> | |
<h1>Welcome to {activity.get('name')}</h1> | |
<button | |
onClick={() => updateActivity(Map({name: 'New name'}))} | |
disabled={isPending(response)} | |
> | |
Update name | |
</button> | |
</div> | |
); | |
const ActivityListCreate = ({activity, createActivity, response}) => ( | |
<div> | |
<h1>Activities</h1> | |
<ul> | |
{activities.map(activity => | |
<li>{activity.get('name')}</li> | |
)} | |
</ul> | |
<button | |
onClick={() => createActivity(Map({name: 'New activity'}))} | |
disabled={isPending(response)} | |
> | |
Create activity | |
</button> | |
</div> | |
); | |
const App = ({ activityId }) => ( | |
<div> | |
<WithItem type={ACTIVITIES} id={activityId} render={({item, update, response}) => ( | |
<ActivityEdit | |
activity={item} | |
updateActivity={update} | |
response={response} | |
/> | |
)}/> | |
<WithCollection type={ACTIVITIES} render={({items, create, response}) => ( | |
<ActivityListCreate | |
activities={items} | |
createActivity={create} | |
response={response} | |
/> | |
)}/> | |
</div> | |
); | |
class WithItem extends React.Component { | |
componentWillMount() { | |
const { type, id } = this.props; | |
this.props.loadItem(type, id); | |
} | |
render() { | |
const { type, id, render, items, responses } = this.props; | |
const isFetching = isPending(responses.getIn([GET_ITEM, type])); | |
const hasData = items.get(type) && items.getIn([type, 'id']) === id | |
if (isFetching && !hasData) { | |
return <Loading />; | |
} | |
return ( | |
<span> | |
{isFetching && <Loading />} | |
{hasData && render({ | |
item: items.get(type), | |
update: this.props.updateItem.bind(type), | |
response: responses.getIn([UPDATE_ITEM, type]) | |
})} | |
</span> | |
); | |
} | |
} | |
function mapStateToProps(state) { | |
return { | |
items: state.items, | |
responses: state.responses, | |
}; | |
} | |
export default connect(mapStateToProps, {loadItem, updateItem})(WithItem); | |
class WithCollection extends React.Component { | |
componentWillMount() { | |
const { type } = this.props; | |
this.props.getCollection(type); | |
} | |
render() { | |
const { type, id, render, collections, responses } = this.props; | |
const isFetching = isPending(responses.getIn([GET_COLLECTIONS, type])); | |
const hasData = collections.get(type); | |
if (isFetching && !hasData) { | |
return <Loading />; | |
} | |
return ( | |
<span> | |
{isFetching && <Loading />} | |
{hasData && render({ | |
collection: collections.get(type), | |
items: collections.getIn([type, 'items']), | |
create: this.props.createItem.bind(type), | |
response: responses.getIn([CREATE_ITEM, type]) | |
})} | |
</span> | |
); | |
} | |
} | |
function mapStateToProps(state) { | |
return { | |
collections: state.collections, | |
responses: state.responses, | |
}; | |
} | |
export default connect(mapStateToProps, {getCollection, createItem})(WithCollection); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment