Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

HOC with wrapped component with asyncConnect #116

Open
ronar opened this issue Jun 12, 2017 · 11 comments
Open

HOC with wrapped component with asyncConnect #116

ronar opened this issue Jun 12, 2017 · 11 comments
Labels

Comments

@ronar
Copy link

ronar commented Jun 12, 2017

Hi! Is it possible to make HOC which wraps asyncConnect'ed component. I can't do this. Because all asyncItems, mapStateToProps and mapDispatchToProps of the Component seem to be dropped.

Say, I've got the Component:

...
const mapStateToProps = state => ({
    ...
});

const asyncItems = [{
    key: 'myItems',
    promise: ({router, store: { dispatch, getState }}) => {}
}];
const enhancer = createHOC();

module.exports = enhancer(asyncConnect(
    asyncItems,
    mapStateToProps,
    mapDispatchToProps,
)(Component));

And HOC itself has the asyncConnect enhancer :)
Is it possible or do I have to abandon this idea at all?

@AVVS
Copy link
Member

AVVS commented Jun 16, 2017

move static over to the enhancer in HOC, that's really the only thing you can do here to get this to work. Generally asyncConnect must be the top HOC

@ronar
Copy link
Author

ronar commented Jun 17, 2017

Okay, it make sense. And how to correctly implement HOC, make a factory which receives asyncItems, mapStateToProps and dispatchProps and returns parametrised enhancer with asyncConnect?

const enhancerFactory = (asyncItems = [], mapStateToProps, dispatchProps) => {
    ...

    function wrapComponent(wrappedComponent) {
        ...
        const enhancer = compose(
            asyncConnect(asyncItems, finalMapStateToProps, dispatchProps)
        );

        return enhancer(hoistNonReactStatic(HOCComponent, WrappedComponent));
    }

    return wrapComponent;
}

@gerhardsletten
Copy link

Had a issue with loadable-components which also needed to be a direct decender of the Route, but then I could use the getComponent in react-router v3 to do the loading, and then send the redux-connect HOC to react-router

gregberge/loadable-components#15

@internetErik
Copy link

@gerhardsletten Any chance you've also been able to get redux-connect and loadable-components to work with react-router v4? Right now I can't see how since async-connect and loadable-components both seem to need to be the top level HOC.

I wouldn't mind trying my hand a pull request to add features to make this possible in redux-connect, but I'd feel better in talking about it with somebody first to plan out what needs to be done. Maybe @AVVS could help provide some direction for me (thanks for this component by the way - it's been very handy)?

I think #118 is related to this, too.

@gerhardsletten
Copy link

gerhardsletten commented Feb 5, 2018

@internetErik No, have not had the time to upgrade for RR4 after redux-connect supports it. But did you see my updated comment here about the need for a static componentId property on the component to ensure that loadable-components can register it?

Also take a look at this article by the airbnb about adding a function for the component in the config. You should then be able to itterate matched routes, and prepare them before you give them to redux-connects loadOnServer function.

Maybe there should be made an example for this. Async loading both data and components is what you expect of an application today

@internetErik
Copy link

@gerhardsletten Thanks for the info! I think I may be able to figure something out from that. (The link to the airbnb article seems to be broken btw.)

@gerhardsletten
Copy link

@internetErik updated the link now in the comment below!

@AVVS AVVS added the question label Feb 16, 2018
@gerhardsletten
Copy link

After upgrading to RR v4 and the latest version of redux-connect, I think that the solution for both data-fetching and code-splitting is about organizing you code. The route-level component can't both be HOC'ed with redex-connect and be lazy-loaded, so you should do data-fetching in the route-level component and move lazy-loading into a child-component. Can't think of any other way to do this, since you don't have a getComponent function with react-router-config, without writing you own helper that both lazy-load and do data-fetching. Maybe this should be mentions in the README.md to save people from spending time looking into this?

@internetErik
Copy link

@gerhardsletten Do you have any example of this you could share by any chance? It would be helpful to me to see some of what you're doing in particular.

@gerhardsletten
Copy link

Hi, this is an example of a controller. You just move the visuals and heavy dependencies into its own component, and just hot-load it from the controller, but keep the asyncConnect hoc on the controller so redux-connect will discover it through react-router-config

import React, { Component } from 'react'
import { connect } from 'react-redux'
import { asyncConnect } from 'redux-connect'
import loadable from 'loadable-components'

import { isLoaded as isPageLoaded, load as loadPage } from 'redux/modules/page'

const Page = loadable(() =>
  import(/* webpackChunkName: "page" */'./Page')
)

@asyncConnect([
  {
    promise: ({ store: { dispatch, getState }, location: { pathname } }) => {
      const promises = []
      if (!isPageLoaded(getState(), pathname)) {
        promises.push(dispatch(loadPage(pathname)))
      }
      return Promise.all(promises)
    }
  }
])
@connect(state => ({
  page: state.page.data,
  error: state.page.error
}))
export default class PageContainer extends Component {
  render() {
    return <Page {...this.props} />
  }
}

@internetErik
Copy link

@gerhardsletten Thanks, this is really helpful to see!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

4 participants