0

Code Sandbox link: Edit broken-worker-9xmm7

and trying to follow this article

On successful login(/auth/login), the user should be routed to the dashboard(/admin/summary). If the login is successful, I am also storing an access token.

I have a PrivateRoute component for this. The problem is that on successful login, the URL is getting updated but the component is not getting rendered.

PS: about the dashboard, this is a single page application so, the dashboard has topbar, sidebar, and the right content and altogether these things are coupled inside <AdminLayout/>. So, in my AppRouter, I have to render the <AdminLayout/> and just any one component.

All the react and redux code is included in the code sandbox.

Nauman
  • 894
  • 4
  • 14
  • 45

1 Answers1

1

Since in your code you create your own history object (it happens in you history.js file, when you call createBrowserHistory()) but doesn't pass it to your Router, nothing happens.

There are 2 possible solutions:

1. Don't create a history object yourself, but use useHistory hook inside your component

Working Demo

With this approach, you should remove history.push from login.actions.js (which imports history) and use history.push in Login.js (which uses useHistory hook):

// login.actions.js
...
loginService.login(userid, password, rememberPassword).then(
    (userid) => {
      dispatch(success(userid, password, rememberPassword));
      // history.push(from); <-- commented out!
    },
    (error) => { ... }
  );
};
...

// Login.js

function handleSubmit(e) {
   ...
   const { from } = {
     from: { pathname: "/admin/summary" }
   };
   history.push(from) // <-- added!
   dispatch(loginActions.login(inputs, from));
   ...
}

useHistory exposes the history object of BrowserRouter (I think this is implied in this official blog post).

2. Create a history object yourself, but pass it to a Router component

Working Demo

This approach would require you to make several changes:

  1. Creating the history object on your own means you become responsible to provide it to a router component, but it can't be a BrowserRouter, but the base Router component (see these Github answers: 1, 2).

  2. Once you import Router (instead of BrowserRouter), you need to get rid of any useLocation and useHistory imports, otherwise you'll get errors.

  3. I also had to unify the history object export and imports, so that it is exported as the default export (i.e., export default history), and it is imported as the default import (i.e., import history from "./history"; instead of import { history } from "./history")

(P.S: this approach can be seen implemented elsewhere on SO, for example here or here (the latter explicitly installs history, but it's not needed in your case).

OfirD
  • 9,442
  • 5
  • 47
  • 90
  • thanks for this. Actually I do have installed `history`. Update: it's now kinda loading the `layout` ie. click login-> blank page with correct `className` in `` is loaded. But not the contents of the page. Now, these contents are coming from `AdminLayout` and I have just updated the sandbox with it. ` ` and this is how I trying to load that in `AppRouter`. Any suggestion where I am going wrong. – Nauman Sep 08 '20 at 09:48
  • 1
    Note that your sandbobox doesn't list `history` as a dependency, that's why I said that in your case it's not necessary. Regarding your update, I don't see it, and you better post the updated sandbox link here in the comments. Please do not remove your original question link, as it would invalidate my answer. I also think that it would be fair to accept my answer, and I would then try help you with your follow up question. – OfirD Sep 08 '20 at 10:12
  • 1
    UPDATED sandbox Link: https://codesandbox.io/s/broken-worker-9xmm7?fontsize=14&hidenavigation=1&theme=dark&view=editor&file=/src/App.js – Nauman Sep 08 '20 at 10:17
  • Thanks. Are you sure that's the updated sandbox? I don't see either my answer's approach 1 or approach 2 implemented. – OfirD Sep 08 '20 at 10:26
  • sorry for the confusion, the approach 1 worked for me. I just added `AdminLayout` code and updated related imports in `AppRouter` – Nauman Sep 08 '20 at 10:28
  • But is approach 1 implemented in the sandbox you linked to in your comment? I don't think so, because `` is not displayed. – OfirD Sep 08 '20 at 10:30
  • 1
    Then of course it won't work :) plus, I don't see the implementation of `AdminLayout` in your updated link (it's also not present in your linked article, so I assume it's your own implementation). Now, once you'd add it, you should also pay attention to the fact that it is placed under a `Switch`, so navigating to `Dashboard` vs `AdminLayout` should be handled by additional code, probably in `PrivateRoute`. – OfirD Sep 08 '20 at 10:43
  • `1)` `Admin.js` is AdminLayout. its related import is commented out in `AppRouter`. `2)` I also updated my question's desc with the article I had followed to write my own code. `3).` can you please, elaborate `placed under a Switch, so navigating to Dashboard vs AdminLayout should be handled by additional code, probably in PrivateRoute` this point. thanks a ton !! – Nauman Sep 08 '20 at 10:48
  • 1
    Sorry, `Admin.js` has many imports that are not present as files. Please uncomment `Admin.js` import, then make sure that your code compiles, and then I'll try to help you further. – OfirD Sep 08 '20 at 11:01
  • sure. done. updated link: https://codesandbox.io/s/broken-worker-9xmm7?fontsize=14&hidenavigation=1&theme=dark&view=editor&file=/src/AppRouter.js – Nauman Sep 08 '20 at 11:04