Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- // this `<Route>` component might make it possible for you to ~generally~
- // upgrade to React Router v4 w/o doing hardly anything to your app for the
- // happy path stuff.
- //
- // This definitely won't work as-is, I haven't run this code, just banged it
- // out when the thought occured to me that it might be possible.
- const { func, object } = React.PropTypes
- const Route = (route) => (
- <Match pattern={route.path} render={(props) => (
- route.children ? (
- <MatchWithRouteLifecycle route={route} {...props}>
- <MatchGroup>
- {React.Children.map(children, (child) => (
- <Route {...child.props}/>
- ))}
- </MatchGroup>
- </Component>
- ) : (
- <MatchWithRouteLifecycle route={route} {...props}/>
- )
- )}/>
- )
- class MatchWithRouteLifecycle extends React.Component {
- static propTypes = {
- route: {
- component: func,
- getComponent: func,
- onEnter: func,
- onChange: func,
- onLeave: func,
- components: object, // NOPE
- getComponents: func, // NOPE
- getChildRoutes: func // NOPE
- },
- location: object,
- path: string,
- pattern: string
- }
- constructor(props) {
- super(props)
- this.state = {
- prevProps: null,
- needingToRunEnterHook: props.route.onEnter,
- needingToGetComponent: props.route.getComponent,
- AsyncComponent: null
- }
- }
- componentDidMount() {
- if (this.state.needingToRunEnterHook) {
- this.runEnterHook()
- }
- if (this.state.needingToGetComponent) {
- this.getComponent()
- }
- }
- componentWillReceiveProps(nextProps) {
- if (!locationsAreEqual(nextProps.location, this.props.location)) {
- if (this.props.onChange) {
- this.runChangeHook(nextHook)
- }
- }
- }
- componentWillUnmount() {
- if (this.props.route.onLeave) {
- this.runLeaveHook()
- }
- }
- getComponent() {
- this.props.route.getComponent((err, AsyncComponent) => {
- this.setState({ AsyncComponent })
- })
- }
- runLeaveHook() {
- const prevState = {}
- this.props.route.onLeave(prevState)
- }
- runEnterHook() {
- const { onEnter } = this.props.route
- const isAsync = onEnter.length === 3
- const nextState = {}
- const replace = () => {}
- if (isAsync) {
- onEnter(nextState, replace, () => {
- this.setState({ needingToRunEnterHook: false })
- })
- } else {
- onEnter(nextState, replace)
- this.setState({ needingToRunEnterHook: false })
- }
- }
- runChangeHook(nextProps) {
- const { onChange } = this.props
- const isAsync = onChange.length === 4
- const prevState = {}
- const nextState = {}
- const replace = () => {}
- if (!isAsync) {
- onChange(prevState, nextState, replace)
- } else {
- this.block(() => {
- onChange(prevState, nextState, replace, this.unblock)
- })
- }
- }
- block(cb) {
- this.setState({ prevProps: this.props }, cb)
- }
- unblock() {
- this.setState({ prevProps: null })
- }
- render() {
- if (
- this.state.needingToRunEnterHook ||
- this.state.needingToGetComponent
- ) {
- return null
- } else {
- const props = this.state.prevProps ?
- this.state.prevProps : this.props
- const { route, params, location, children } = props
- const Component = this.state.AsyncComponent || route.props.component
- const v3Props = { ...route, params, location, children }
- return <Component {...v3Props}/>
- }
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement