React Router with RefluxJS - Changing route Programmatically from a Store

1.5k views Asked by At

In my project I deiced to include React Router. One of my Reflux Stores need to figure out the path based on some BL and than change it. First I've tried including the Navigation mixin inside the Store and running this.transitionTo("Foo"); which threw an error : "Uncaught TypeError: Cannot read property 'router' of undefined".

Someone suggested that : "this.transitionTo is probably accessing the router property through contexts (this.context.router) which do not exist in RefluxJS stores" ... Which I understand.

However there must be a way to change the router path from a Store Programmatically, or any given external JS Module.

My Code goes something like this:

// routes.js
//////////////////////////////////////////////////////////
var Router  = require('react-router');
var Route   = Router.Route; 
var App     = require('./app');
var Comp    = require('./components/comp');

var routes = (
    <Route path='/' handler={App}>      
        <Route name='Foo' path='/foo' handler={Comp}/>              
    </Route>
);

module.exports = routes;

// main.js
//////////////////////////////////////////////////////////
var React   = require('react');
var Router  = require('react-router');
var routes  = require('./Routes');

var appElement = document.getElementsByTagName('body');

Router.run(routes, Router.HistoryLocation, function(Root, state) {
    React.render(<Root params={state.params} query={state.query} />, appElement);
});

// comp.js
//////////////////////////////////////////////////////////
var React      = require("react");
var Reflux     = require("reflux");
var Actions    = require("../actions/actions.js");
var SomeStore  = require("../stores/some-store.js");

var Comp = React.createClass({

    render: function() {
        return (
            <h1>Hello World</h1>    
        );
    }
});

module.exports = Comp;

// store.js
//////////////////////////////////////////////////////////
var SomeStore = Reflux.createStore({    

    onSomeAction: function() {
        // CHANGE ROUTER PATH HERE TO /foo
    }

});

module.exports = SomeStore;

Any help will be appreciated!

2

There are 2 answers

2
Colin Ramsay On

Reflux actions return a promise, so rather than doing this in the store (which IMO is wrong) you can do it in your component:

Actions.someAction().then(function() {
    // route transition
});

Whether this is completely right... well, I'm not sure the community has really settled on an opinion.

0
Björn Boxstart On

The router is only known by the components (React views). You need to pass the router from the context as a parameter in your action. That way, you can use this parameter to make a transition to a different route. I've been using it this way.

I have something like below in one of my action listeners in a store.

 _onMyAction: function (router) {
    MyApi.doSomething()
        .then(function (id) {
            // do something ...
            router.transitionTo('myNewRoute', { ref: id });
        })
        .catch(function(message) {
            // handle message
        });
}