0

So in my app I have a login-component and an authenticator-component. The last one works with QR code authorization etc.

Since the package "node-sass" is deprecated now, I changed to the "sass" NPM package. I had to upgrade "react-router" and "react-router-dom" as well to their latest version (6...).

Here's my dependencies:

 "dependencies": {
    "@material-ui/core": "^4.11.0",
    "@material-ui/icons": "^4.9.1",
    "@material-ui/lab": "^4.0.0-alpha.56",
    "@react-pdf/renderer": "^1.6.12",
    "@reduxjs/toolkit": "^1.4.0",
    "@testing-library/jest-dom": "^4.2.4",
    "@testing-library/react": "^9.5.0",
    "@testing-library/user-event": "^7.2.1",
    "axios": "^0.20.0",
    "caniuse-lite": "^1.0.30001197",
    "moment": "^2.29.1",
    "qrcode.react": "^1.0.0",
    "qs": "^6.9.4",
    "react": "^16.13.1",
    "react-async": "^10.0.1",
    "react-dom": "^16.13.1",
    "react-fade-in": "^1.1.0",
    "react-icons": "^3.11.0",
    "react-movable": "^2.5.3",
    "react-outside-click-handler": "^1.3.0",
    "react-qr-reader": "^2.2.1",
    "react-redux": "^7.2.1",
    "react-router": "^6.0.2",
    "react-router-dom": "^6.0.2",
    "react-scripts": "3.4.3",
    "redux": "^4.0.5",
    "redux-axios-middleware": "^4.0.1",
    "redux-devtools-extension": "^2.13.8",
    "redux-thunk": "^2.3.0",
    "sass": "^1.43.4",
    "xlsx": "^0.16.8"
  },

So my next step was to change everything from "react-router" and "react-router-dom" to use their latest items, like "useHistory" was changed to "useNavigate" etc.

Their "history.push("/route")" was also changed to "navigate("/route")" now, so I changed those as well.

And lastly, they removed the "withRouter" function from their package, which used to be required for navigation to work inside main App. It used to be like this:

export default withRouter(App);

But now this is the hook that it replaces:

import React from 'react';
import { useNavigate, useLocation } from 'react-router-dom';

export const withRouter = (Component) => {
  const Wrapper = (props) => {
    const navigate = useNavigate();
    const location = useLocation();
    
    return (
      <Component
        {...props}
        navigate={navigate}
        location={location}
      />
    );
  };
  
  return Wrapper;
};  

And then you import that one, and use "withRouter(App)" etc...

Here's (part of) my App Routing:

 return (
    <ThemeProvider theme={theme}>
        <Loading />
        <Header
          menuHandler={() => {
            changeMenu(!showMenu);
          }}
          setActive={setActive}
        />
        <main className="main">
          <MenuBar
            showMenu={showMenu}
            toggleMenu={() => changeMenu(!showMenu)}
            active={active}
            setActive={setActive}
          />
          <Container className="main__container" id="main__container">
            <MySnackbar />
            <Modal />
            <Routes>
              <Route
                path="/scanner"
                element={
                  <ScannerScreen />
                }
              />
              <Route
                path="/authenticator"
                element={
                  <Authenticator />
                }
              />
              <Route 
                path="/login" 
                element={
                  <Login />
                }
              />
              ...

As you can see, where it says now "Routes" is where it used to say "Switch" in previous "react-router-dom" versions.

I used to navigate between pages, like so:

import { useNavigate } from "react-router-dom";

... 

const navigate = useNavigate();  

...

navigate("/authenticator", {
    authMode: "login",
    username: user.username,
});

As you can see, I'm using the V6 "navigate" from "react-router-dom" now instead of the previous "history.push('/authenticator')" for example.

This navigation works, however no props are passed (like authMode & username) and the props are always "undefined" in the target/new component, when here/source component they are filled in.

No matter what I do, props are always undefined, like so:

// both authMode & username will be undefined
const Authenticator = ({ authMode, username }) => {...}

// props will be undefined
const Authenticator = (props) => {...}

// both of these will return undefined values
const Authenticator = () => {
      const { authMode, username } = useParams();
      const { authMode, username } = useLocation();
}

Does anyone have any idea how I can properly pass props from Login to my Authenticator, using Javascript, like so:

navigate("/authenticator", {
    authMode: "login",
    username: user.username,
});

Thanks!

Tempuslight
  • 1,004
  • 2
  • 17
  • 34

1 Answers1

0

So, of course, right after posting a stackoverflow post I kept on digging and finally found "a" solution myself. I'm not sure if this is the best way, but here it is.

Looking at this post: https://stackoverflow.com/a/64566486/3384458 , props are no longer "just" passed to other components. It has to go via the "location" prop now.

So now I have to do it like this, in my Login-component:

navigate("/authenticator", {
    state: {
        authMode: "login",
        username: user.username,
    }
});

You have to set the "location.state" prop of "location", like above. Now the "location.state" prop will contain my object with "authMode" and "userName".

In my Authenticator-component, I do it like this now:

const { authMode, username } = useLocation().state;

Here's another helpful link for react-router v6: https://remix.run/blog/react-router-v6

Tempuslight
  • 1,004
  • 2
  • 17
  • 34