Skip to content
This repository has been archived by the owner on Oct 26, 2018. It is now read-only.

redirect AND render new url #561

Closed
damianobarbati opened this issue Apr 13, 2017 · 12 comments
Closed

redirect AND render new url #561

damianobarbati opened this issue Apr 13, 2017 · 12 comments

Comments

@damianobarbati
Copy link

I'm simply trying to redirect browser to new url in my dispatch: typical scenario is dispatching an action which sign in with an ajax request and then redirect the user to /home.

  • "push" action from react-router-redux just changes url in browser but router is not rendering new component
  • transientTo from react-router does not exist anymore and anyway it was not a dispatchable action which can be called within a dispatched action

It's so stressing to find proper documentation and working together with react-router and react-router-redux.

Using:

"react-router": "^4.0.0",
"react-router-dom": "4",
"react-router-redux": "next",

Store created as:

import { createStore, combineReducers, applyMiddleware } from 'redux';
import { composeWithDevTools } from 'redux-devtools-extension';
import { routerMiddleware, routerReducer, syncHistoryWithStore } from 'react-router-redux';
import thunkMiddleware from 'redux-thunk';
import promiseMiddleware from 'redux-promise';
import createLogger from 'redux-logger';

import { REHYDRATE } from 'redux-persist/constants';
import { persistStore, autoRehydrate } from 'redux-persist';
import createActionBuffer from 'redux-action-buffer';

import config from '../../config/config.js';
import auth from '../auth/auth.reducer.js';
import notification from '../notification/notification.reducer.js';
import forms from '../form/form.reducer.js';

const defaultReducers = { config: () => config, auth, notification, forms, routing: routerReducer };

const getStore = ({ reducers, history }) => {
    reducers = { ...defaultReducers, ...reducers };
    const finalReducer = combineReducers(reducers);
    const historyMiddleware = routerMiddleware(history);
    const loggerMiddleware = createLogger();
    const finalMiddleware = applyMiddleware(
    	thunkMiddleware,
    	promiseMiddleware,
    	historyMiddleware,
        loggerMiddleware,
    	createActionBuffer(REHYDRATE),
    );
    return createStore(finalReducer, composeWithDevTools(finalMiddleware, autoRehydrate({ log: false })));
};
export default getStore;

Router created as:

import React from 'react';

import { ConnectedRouter } from 'react-router-redux';
import { Switch, Route, Redirect } from 'react-router-dom';
import createHistory from 'history/createBrowserHistory'

export const history = createHistory({ basename: '/user' });

import Auth from '../auth/Auth';
import NotFound from './pages/notfound/NotFound';
import Layout from './pages/layout/Layout';
import Home from './pages/home/Home';

export default class Router extends React.Component {
    render() {
        return (
            <ConnectedRouter history={history}>
                <Layout>
                    <Switch>
                        <Route exact path="/" render={() => <Redirect to="/home" />} />
                        <Route exact path="/auth/:token?" component={Auth} />
                        <Route exact path="/home" component={Home} />
                        <Route path="*" component={NotFound} />
                    </Switch>
                </Layout>
            </ConnectedRouter>
        );
    }
}

Attempt to redirect after sign in:

import { push } from 'react-router-redux';

export const setToken = async ({ token }) => {
    return async (dispatch) => {
        dispatch({ type: SIGN_IN, value: token });
        dispatch(push('/home'));
    };
};
@timdorr
Copy link
Member

timdorr commented Apr 14, 2017

This is a bug tracker, not a support system. For usage questions, please use Stack Overflow or Reactiflux. Thanks!

@timdorr timdorr closed this as completed Apr 14, 2017
@damianobarbati
Copy link
Author

Thanks for answering @timdorr!
The post is already there http://stackoverflow.com/questions/43411608/react-router-redux-redirect-and-render-new-url.
Do you realize that nobody is ever going to answer because nobody is able to answer?

@damianobarbati
Copy link
Author

damianobarbati commented Apr 17, 2017

After countless hours investigating the bug I found the withRouter wrapper/decorator.
It does not work: push action does not trigger component rendering after url change, even after wrapping routed & connected components with it.

@withRouter
@connect((state, props) => ({
	database: state.database,
}))
export default class Home extends React.Component {

https://github.com/ReactTraining/react-router/blob/master/packages/react-router/docs/guides/blocked-updates.md

@steodor
Copy link

steodor commented Jun 7, 2017

@damianobarbati how did you solve the issue in the end? or what did you end up doing?

@damianobarbati
Copy link
Author

damianobarbati commented Jun 7, 2017

@steodor I solved so many issues about this react-router + react-router-redux I can't even remember how I did fix this one!
Try to use the withRouter decorator on your main component (the one outside the router)

<ConnectedRouter history={history}>
                <Layout> <== withRouter on this 
                    <Switch>
                        <Route

@steodor
Copy link

steodor commented Jun 7, 2017

Thanks! i fiddled with withRouter for a while and finally got it working, yay :)

@juampick
Copy link

Thanks @damianobarbati !
Anyone with react-router": "^3.0.5" ? Not working for me the withRouter()
Using also react-router-redux v4.0.8
Example:

export default withRouter(connect(mapStatesToProps, mapDispatchToProps)(App));

Not working for me, any other thoughts there? we are really hang here!

Thanks to all,
JP

@vaibhav-systango
Copy link

@damianobarbati Did you get solution for this . Please help it's urgent

@damianobarbati
Copy link
Author

@vaibhav-systango if your component is not re-rendering then its props (and state) are not changing either.
If your component is supposed to re-render when the "location" changes then be sure "location" prop is passed to the component.
Long story made short, use the @withRouter hoc:

import { withRouter } from 'react-router-dom';
@withRouter
class MyComponent {

Now location is passed as a prop to MyComponent.
When location changes then MyComponent re-renders.

More about this: https://github.com/ReactTraining/react-router/blob/master/packages/react-router/docs/api/withRouter.md

@vaibhav-systango
Copy link

@damianobarbati But when I run dispatch(push('url')), even the url doesn't change?

@damianobarbati
Copy link
Author

@vaibhav-systango then you didn't apply the router reducer into your redux store maybe?
Can you share the parts of your code where you're implementing it?

@vaibhav-systango
Copy link

@damianobarbati Yes I wasn't injecting router in redux, currently it works with react router dom router.history.push thing. Thanks for your suggestion man. Merry Christmas ;)

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

No branches or pull requests

5 participants