React Router v4 Navigate from MobX store action?

Viewed 3445

I am trying to have react router v4 navigate from an action in a store without explicitly passing the history prop to each store action that needs to navigate after some logic runs.

I am looking for something like this to work:

import { NavigationStore } from 'navigation-store';

class ContactStore {
  @action contactForm(name, message){
    // Some logic runs here

    // Then navigate back or success

    // Go back
    NavigationStore.goBack();

    // Or Navigate to Route
    NavigationStore.push('/success'); 
  }
}

Of course NavigationStore doesn't exist (I wouldn't know what to put in it from React Router to make it work), but I am looking to import a mobx navigation store that I can use to navigate to and from anywhere in the app (component or store) with the same api as react-router

How to do it?

Update:

RR4 doesn't give us a way to navigate from a store's action. I am trying to navigate just like above using RR4. I just need to know what navigation-store should contain to so I can:

  1. import { NavigationStore } from 'navigation-store'; anywhere (component/store), also history aware, to be able to navigate from anywhere.
  2. NavigationStore.RR4Method(RR4MethodParam?); where RR4Method would be the available RR4 navigation options like push, goBack, etc.. (This is how navigation should happen)

Update 2:

So the url updates now from the NavigationStore.push('/success'); but no webpage refresh happens.

Here is navigation-store.js

import { observable, action } from 'mobx'
import autobind from 'autobind-decorator'
import createBrowserHistory from 'history/createBrowserHistory'

class NavigationStore {
  @observable location = null;
  history = createBrowserHistory();

  @autobind push(location) {
    this.history.push(location);
  }
  @autobind replace(location) {
    this.history.replace(location);
  }
  @autobind go(n) {
    this.history.go(n);
  }
  @autobind goBack() {
    this.history.goBack();
  }
  @autobind goForward() {
    this.history.goForward();
  }
}

const navigationStore = new NavigationStore();

export default navigationStore;

Here is app.js

import React from 'react'
import { Provider } from 'mobx-react'
import { BrowserRouter as Router, Route } from 'react-router-dom'
import Contact from 'screens/Contact'
import Success from 'screens/Success'

export default class App extends React.Component {
  render() {
    return (
      <div>
        <Provider>
          <Router>
            <div>
              <Route path='/contact' component={Contact} />
              <Route path='/success' component={Success} />
            </div>
          </Router>
        </Provider>
      </div>
    );
  }
}

Once the url changes to /success, nothing happens to the webpage instead of loading the matching component Success in this case. Still stuck here..

Update 3 (solution):

This helped I am putting it here as a reference for others as it was very frustrating for me.

In app.js I had to change:

import { BrowserRouter as Router, Route } from 'react-router-dom'
<Router>

to

import { Route } from 'react-router-dom'
import { Router } from 'react-router'
import navigationStore from 'stores/navigation-store'
<Router history={navigationStore.history}>

I hope this helps others :)

1 Answers
Related