10

action.js:

export const login = creds => {
    console.log(`${url}/login`);
    const requestOptions = {
        method: "POST",
        headers: {
            Accept: "application/json",
            "Content-Type": "application/json"
        },
        body: creds
    };

    return function(dispatch) {
        dispatch({ type: LOGIN_REQUEST });
        function timer() {
            return fetch(`${url}/login`, requestOptions).then(response => {
                if (!response.ok) {
                    console.log(response);
                    return response.json().then(json => {
                        var error = new Error(json.message);
                        error.response = response;
                        throw error;
                    });
                } else {
                    console.log("3");
                    return response.json();
                }
            }).then(user => {
                if (user.message === "ok") {
                    localStorage.setItem("token", user.token);
                    dispatch({ type: LOGIN_SUCCESS, payload: user.token });
                    window.location.href = `${app}/dashboard`;
                } else {
                    const error = user.message;
                    throw new Error(error);
                }
            }).catch(function(error) {
                dispatch(loginError(error));
            });
        }
        setTimeout(timer, 5000)
    }
};

I am unable to redirect in a single-page manner to my dashboard, I searched a lot but I didn't get anything useful. I am using React Router v4. Can you please suggest whether I am doing this user login with JWT the right way or not.

Antti29
  • 2,953
  • 12
  • 34
  • 36
tapan dave
  • 293
  • 2
  • 8
  • 18
  • I am not familiar with react, but I think it might be a misunderstanding of window.location.href, If you choose to use window.location.href, you should specify the whole path, so for instance maybe window.location.href = http://localhost:5000/${app}/dashboard. I think this is quite a nice source, https://stackoverflow.com/questions/7077770/window-location-href-and-window-open-methods-in-javascript – cruise_lab Oct 26 '17 at 12:53

3 Answers3

10

create a your own history in history.js file using this history library.

//history.js
import createHistory from 'history/createBrowserHistory'

const history = createHistory()

export default history

Supply it to your router:

<Router history = {history}>.....</Router>

Then you can use this history object to redirect from anywhere. In your action:

import history from './history'
history.push(`${app}/dashboard`)
The Dembinski
  • 1,469
  • 1
  • 15
  • 24
Anurag Awasthi
  • 6,115
  • 2
  • 18
  • 32
  • hey,it worked very well, but i have create a separate function for authentication for route,but its seems it is now working,here is link for code https://gist.github.com/5c6c14e2d2503b4d22872b983bccd978 , is this a proper approach? – tapan dave Oct 26 '17 at 13:13
  • What is this `${app}` of which you speak? – Josh M. Aug 20 '18 at 15:12
  • or you can just pass the history props to login action. – anuradha Aug 28 '18 at 13:43
3
  1. You can add react-router-redux which will conveniently add all routing info to the Redux state, but also you can use push from react-router-redux by:

    dispatch(push('/dashboard'))
    

    You can access it by

    import { push } from 'react-router-redux'
    
  2. I think you are not doing anything wrong with JWT. I would abstract your fetch call with the helper function. I assume you need to add your access token to all future requests after authorization, and using helper function you can do it easier and keep you code cleaner.

Yoshi
  • 104
  • 1
  • 4
  • thanks for the suggestion, but i tried react-router-redux,but was not working – tapan dave Oct 26 '17 at 13:14
  • 1
    You need to: 1. `import { syncHistoryWithStore, routerMiddleware } from 'react-router-redux';` 2. `import { createStore, applyMiddleware, compose } from 'redux';` 3. `import { BrowserRouter } from 'react-router-dom';` 4. `const store = createStore([YOUR ROOT REDUCER], applyMiddleware(routerMiddleware(browserHistory),));` // You might need to compose middleware if you are using others. 5. `const history = syncHistoryWithStore(browserHistory, store);` 6. `` It's a bit of setup, but it worth it. Let me know if you need my help with it. – Yoshi Oct 26 '17 at 13:25
  • 1
    Btw, after all above you can use `browserHistory` from `react-router` in your component by: `browserHistory.push('/login')`. It might be useful to redirect user back to login if anonymous needs to access page which is available for authenticated users only. – Yoshi Oct 26 '17 at 13:28
  • ok,thanks if i need help i will let you know,but using history api is also easy and fast solution,right? – tapan dave Oct 26 '17 at 13:33
  • Sure it is. If you need to achieve just simple redirect, history api is probably the best option. – Yoshi Oct 26 '17 at 20:27
2

window.location.href will hit your server and you'll loose all the benefits of a single page application, you should use a client side routing instead with the history object

In this scenario a good solution could be pass a callback from the component that triggers the first dispatch containing a history.push to the new state

e.g.

Assuming that inside your component props you have access to history

login(body, () => {
  this.props.history.push('/dashboard');
})

then in place of window.location.href = ${app}/dashboard you invoke the callback

Karim
  • 8,454
  • 3
  • 25
  • 33