Last active
January 24, 2017 17:14
-
-
Save taion/66b6ce17b601568d7ad3321e3dda8b8d to your computer and use it in GitHub Desktop.
React Router data fetching
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
// Define your components like: | |
class MyComponent extends React.Component { | |
static fetchData = (params) => { | |
// return an action here. | |
}; | |
/* ... */ | |
} | |
function fetchComponentData(component, store, params) { | |
if (component.fetchData) { | |
store.dispatch(component.fetchData(params)); | |
}; | |
} | |
export default store => ({ | |
createRouterContext: (child, { components, params }) => { | |
for (const component of components) { | |
if (!component) { | |
continue; | |
} | |
if (typeof component === 'object') { | |
Object.keys(component).forEach(key => { | |
fetchComponentData(component[key], store, params); | |
}); | |
continue; | |
} | |
fetchComponentData(component, store, params); | |
} | |
return child; | |
}, | |
}); |
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
// Define your routes like: | |
const myRoute = ( | |
<Route | |
component={myComponent} | |
fetchData={params => /* action */} | |
/> | |
); | |
export default store => ({ | |
createRouterContext: (child, { routes, params }) => { | |
routes | |
.map(route => route.fetchData) | |
.filter(fetchData => fetchData) | |
.forEach(fetchData => store.dispatch(fetchData(params))); | |
return child; | |
}, | |
}); |
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
ReactDOM.render( | |
<Router | |
history={history} | |
routes={routes} | |
render={applyRouterMiddleware(useFetchData(store))} | |
/>, | |
container | |
); |
Discovered a bug with the above. Here's a more complete resolution:
import React from 'react'
class DispatcherContext extends React.Component {
_fetchData() {
const { action, dispatch } = this.props
dispatch(action())
}
// We trigger a fetchData call the first time we're loaded, every time.
//
componentDidMount() { this._fetchData() }
// If this component is passed different children at any point, we want to
// trigger another fetchData call.
//
// Just putting a blanket update here tends to lead to infinite loops.
//
componentDidUpdate(previous) {
const previousName = previous.children.type.displayName
const currentName = this.props.children.type.displayName
if (previousName !== currentName) { this._fetchData() }
}
// We're a bare wrapper around a component with fetchable actions.
//
render() { return this.props.children }
}
export const dispatcherContext = store => {
// We want to wrap every component with a fetchData static property. I.E.,
// fetchables.
//
const renderRouteComponent = child => {
if (child.type.fetchData) {
return(
<DispatcherContext dispatch={ store.dispatch }
action={ child.type.fetchData }>
{ child }
</DispatcherContext>
)
}
return child
}
return { renderRouteComponent }
}
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
@kilianc, I just played with this example and came up with this:
Which works with the component definition he showed at the top of this gist.