React-Router & MobX - Provider

11,364

If it's a web app, react-router-dom should be used.

Here is the correct way to inject store with Provider https://github.com/mobxjs/mobx-react#observer

I wrote a solution for your code without using decorator, so it supports create-react-app:

import React, { Component } from 'react';
import { Provider, Observer } from 'mobx-react';
import { observable } from 'mobx';
import { BrowserRouter, Switch, Route, Link, Redirect } from 'react-router-dom';

const myStore = observable({
  home: 'Home',
  cat: 'Cat',
});

const Home = () => (
  <Observer 
    inject={stores => ({ myStore : stores.myStore })}
    render={props => (<section><h1>{props.myStore.home}</h1></section>)}
  />
);

const Cat = () => (
  <Observer 
    inject={stores => ({ myStore : stores.myStore })}
    render={props => (<section><h1>{props.myStore.cat}</h1></section>)}
  />
);

class App extends Component {
  render() {
    return (
      <BrowserRouter>
        <Provider myStore={myStore}>
          <div className="App">
            <header className="App-header">
              <nav>
                <ul>
                  <li><Link to="/home">HOME</Link></li>
                  <li><Link to="/cat">CAT</Link></li>
                </ul>
              </nav>
            </header>
            <Switch>
              <Route path='/home' exact component={Home} />
              <Route path='/cat' exact component={Cat} />
              <Redirect from="/" to="/home" />
            </Switch>
          </div>
        </Provider>
      </BrowserRouter>
    );
  }
}

export default App;

All the components are in App.js file. There is no change in default index.js from create-react-app.

Note:
The another way to doing this, it's to simply create a singleton class for the store and use export default new Store() to make it available to all components. The class itself doesn't have to be observable, but its properties do.

Share:
11,364

Related videos on Youtube

Emixam23
Author by

Emixam23

Working on Go and C# for the back, ReactJs for the web, Xamarin for the mobile :) Familiar with Azure/GoogleCloudPlatform and their respective ecosystems Some skills? Kubernetes, Docker, Gitlab (including CI), MongoDB, Cassandra, SQL, Redis, REST/gRPC APIs (using Protobuf), Message Brokers (PubSub, RabbitMQ), etc... Emixam23? Just a story of a boy named Maxime born on the 23rd of November

Updated on May 25, 2022

Comments

  • Emixam23
    Emixam23 almost 2 years

    I am trying to access my store from every component page I have, so I followed the following tutorial in order to connect React Router & MobX.

    http://frontendinsights.com/connect-mobx-react-router/

    However, I am facing a problem at The MobX way – Provider component.

    This is the code exmaple:

    import { Provider } from 'mobx-react';
    import usersStore from './stores/usersStore';
    import itemsStore from './stores/itemsStore';
    
    const stores = { usersStore, itemsStore };
    
    ReactDOM.render(
      <Provider {...stores}>
        <Router history={history}>
          <Route path="/" component={App}>
          </Route>
        </Router>
      </Provider>,
      document.getElementById('app')
    );
    

    I tried to do the same in index.js

    import React from 'react'
    import { render } from 'react-dom'
    import { Router, hashHistory, Route, IndexRedirect } from 'react-router'
    import App from './webapp/App'
    import Home from './components/pages/Home'
    import Dogs from './components/pages/Dogs'
    import Cats from './components/pages/Cats'
    import Provider from 'mobx-react'
    import RootStore from './webapp/stores'
    
    const store = RootStore
    
    render((
      <Provider rootStore={store}>
        <Router history={hashHistory}>
            <Route path="/" component={App}>
              <IndexRedirect to="/home" />
              <Route path="/home" component={Home}/>
              <Route path="/dogs" component={Dogs}/>
              <Route path="/cats" component={Cats}/>
            </Route>
          </Router>
        </Provider>
    ), document.getElementById('app'))
    

    However, because of <Provider/>, I am getting an error:

    Warning: React.createElement: type should not be null, undefined, boolean, or number. It should be a string (for DOM elements) or a ReactClass (for composite components).

    Why am I getting that? It should work doesn't it?

    Thanks for any help !

    • arthurakay
      arthurakay over 6 years
      If you wrap the <Router> inside a <div> does that solve things?
    • Emixam23
      Emixam23 over 6 years
      I will give a try but why would it makes it work?