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

Dynamically imported module in react won't react to Mobx observable #966

Closed
ghost opened this issue Apr 26, 2017 · 6 comments
Closed

Dynamically imported module in react won't react to Mobx observable #966

ghost opened this issue Apr 26, 2017 · 6 comments

Comments

@ghost
Copy link

ghost commented Apr 26, 2017

I load a react component dynamically (via webpack's import('module').then) into my bundle. The problem is that the component won't react to Mobx observable's changes. If i import the module the normal way everything works as intended.

Looking at Mobx dev tools i can see that when the component is statically imported, when the observable changes i see that the component re-renders:

Updated[email protected]’: ([email protected]) (was ([email protected])) Scheduled async reaction ‘Reviews#0.render()’ Reaction ‘$Reviews#0.render()’

In contrary when i use code splitting i don't see any render invoked:

Updated[email protected]’: ([email protected]) (was ([email protected]))

Bellow is my code with test data

`class ReviewsStore { // My store
@observable profile = {};

@action
getProfile() {
    $.ajax({
            url
        })
        .then(action((data) => {
            this.profile = {
                user: 'John Doe',
                userid: 123,
                followers: 25,
                reviewsCount: 22,
                reviews: [{
                        body: 'Lorem ipsum ',
                        date: '20/12/2016',
                        rating: 4.5,
                    },
                    {
                        body: 'Lorem ipsum dolor sit',
                        date: '23/12/2016',
                        rating: 4.2,
                    },
                ],
            };

        }));
}

}

@observer class Reviews extends Component { // My View
constructor() {
super();
this.getProfile = this.getProfile.bind(this);
this.state = {
asyncModule: null,
};
}

getProfile(id) {
    this.props.store.getProfile(id)
    import ('../components/reviews/user-profile')
    .then(({
        default: Profile
    }) => {
        this.setState({
            asyncModule: < Profile user = {
                this.props.store.profile
            }
            />,
        });
    });
}

render() {
    return ( <
        div > {
            this.state.asyncModule
        } <
        /div>
    );
}

}`

I'd be grateful for some help, i've been struggling with this issue for more than a week. Thank you in advance!

@suprise
Copy link

suprise commented May 6, 2017

@sgus May be you can try this:

render() {
    console.log(this.props.store. profile)   //add this
    return ( <
        div > {
            this.state.asyncModule
        } <
        /div>
    );
}

because may be MobX only collect dependences which appearance in the render() method.

@ghost
Copy link
Author

ghost commented May 8, 2017

@suprise Thank you for replying,
I added the console log in my wrapper component and one in my asyncedModule,

At first i see it logs "Object {$mobx: ObservableObjectAdministration}" and the same in my asyncedModule and then the wrapper component rerenders (because the action to get the data is asynchronous) and console logs the correct object, but i don't see any render from the asyncedModule.

I hope i gave you an idea.

@mweststrate
Copy link
Member

@sgus are you sure mobx is not bundled into your splitted bundle as well? Like react, mobx should be unique to be able to operate!

@mweststrate
Copy link
Member

Othwerise, please provide a minimal reproduct repo

@ghost
Copy link
Author

ghost commented May 26, 2017

Hi @mweststrate thank you very much for taking the time again.
i made a simplified version here https://gitlab.com/Sgus/mobx-code-splitting-demo

Basically, i have a store with an observable called id, with initial value 3, when you press the button (there is only one button) i load the asynced module which the id, and i update the observable after 3 seconds.
The normally loaded module updates but the async module won't.

I hope i make sense!
Thank you in advance!

@mweststrate
Copy link
Member

Just looked at your example. Your problem does not relate to mobx. The problem is that in App you just render AsyncProduct once, with the store id at that time, and store it in your state. The solution is to not store an element in your state, but the component instead, and render the component, not the element as part of your render(), e.g. render should have something like <this.state.asyncModule id={this.props.store.id} />

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

No branches or pull requests

2 participants