How can I get the params from the url with React?

12,829

Solution 1

You can use withRouter for getting router information such as location, history, path, and params.

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

...

const VerifyAccount = withRouter(props) => {
  const { token, email } = props.match.params;
  console.log("toke, email: ", token, email)     // And also show me how it looks!!!
  ...
}

And you should define your route like this.

<Route path='/verify-account/:token/:email' component={VerifyAccountPage} />

And you should call like this:

https://your-domain/verify-account/[token]/[email]

This will work.

Solution 2

Route match params are not the same thing as URL query string parameters.

You'll want to access the query string from the location object.

{
  key: 'ac3df4', // not with HashHistory!
  pathname: '/somewhere',
  search: '?some=search-string', <-- query string
  hash: '#howdy',
  state: {
    [userDefined]: true
  }
}

React-router-dom query parameters demo

They create a custom useQuery hook:

const useQuery = () => new URLSearchParams(useLocation().search);

For your use case, on the page rendering the VerifyAccountPage you want to then extract the query string parameters. Given path='/verify-account?token=:token&email=:email':

const query = useQuery();

const email = query.get('email');
const token = query.get('token');

Class-based component ?

If VerifyAccountPage is a class-based component then you will need to access props.location and process the query string yourself in a lifecycle method. This is because React hooks are only validly used by functional components.

componentDidMount() {
  const { location } = this.props;
  const query = new URLSearchParams(location.search);
  
  const email = query.get('email');
  const token = query.get('token');
  ...
}

Note regarding path

path='/verify-account?token=:token&email=:email'

The path params are only relevant in the path portion of a URL, you can't define params for the queryString portion of the URL. The above path is equivalent to path='/verify-account' from react-router-dom's perspective.

Share:
12,829

Related videos on Youtube

uberrebu
Author by

uberrebu

Updated on June 04, 2022

Comments

  • uberrebu
    uberrebu almost 2 years

    I am trying to setup verify account with react and have the following in my App.js file

    App.js

    import SigninPage from './pages/signin';
    import ResetPasswordPage from './pages/resetPassword'
    import VerifyAccountPage from './pages/verifyAccount'
    ...
    ...
    import { useHistory } from 'react-router';
    import { logout } from './utils/auth';
    
    function App() {
    
      const history = useHistory();
      
      return (
        <Router>
          <Switch>
            <Route path='/' component={Home} exact />
            <Route
                path="/signout"
                render={() => {
                  logout();
                  history.push('/');
                  return null;
                }}
            />
            <Route path='/signin' component={SigninPage} exact />
            <Route path='/reset-password?reset-password-token=:resetPasswordToken' component={ResetPasswordPage} />
            <Route path='/verify-account?token=:token&email=:email' component={VerifyAccountPage} exact />
          </Switch>
        </Router>
      );
    }
    
    export default App;
    

    and in my VerifyAccountPage component have the following

    import { Redirect } from 'react-router-dom';
    import { useHistory } from 'react-router';
    import { verifyAccount, isAuthenticated } from '../../utils/auth';
    
    
    const VerifyAccount = () => {
    
      const { token, email } = this.props.match.params
      const history = useHistory();
      const [error, setError] = useState('');
    
      const handleGet = async (e) => {
        e.preventDefault();
        setError('');
        try {
          const data = await verifyAccount(token, email);
    
          if (data) {
            history.push('/');
          }
          console.log(data);
        } catch (err) {
          if (err instanceof Error) {
            // handle errors thrown from frontend
            setError(err.message);
          } else {
            // handle errors thrown from backend
            setError(err);
          }
        }
      };
    
      return isAuthenticated() ? (
        <Redirect to="/#" />
        ) : (  
        <>
          <Container>
            <FormWrap>
              <Icon to='/'>mywebsite</Icon>
              <FormContent>
                <Form action='#'>
                  <FormH1>Verify Account</FormH1>
                  <Text>Account has been verified!</Text>
                </Form>
              </FormContent>
            </FormWrap>
          </Container>
        </>
      );
    };
    
    export default VerifyAccount;
    

    and here is verifyAccount.js page

    import React from 'react';
    import VerifyAccount from '../components/VerifyAccount';
    import ScrollToTop from '../components/ScrollToTop';
    
    function VerifyAccountPage() {
      return (
        <>
          <ScrollToTop />
          <VerifyAccount />
        </>
      );
    }
    
    export default VerifyAccountPage;
    

    here is

    index.js

    import React from 'react';
    import ReactDOM from 'react-dom';
    import App from './App';
    
    ReactDOM.render(
      <React.StrictMode>
        <App />
      </React.StrictMode>,
      document.getElementById('root')
    );
    

    but this is not working and when I go to the link https://mywebsite.com/verify-account?token=3heubek&[email protected] nothing happens other than a 200 or 304 status code

    no request is sent to the API so means that the params are not getting pulled out

    can anyone point me to what is going on?

    package versions used from package.json file

      "dependencies": {
        "@testing-library/jest-dom": "^4.2.4",
        "@testing-library/react": "^9.3.2",
        "@testing-library/user-event": "^7.1.2",
        "react": "^16.13.1",
        "react-dom": "^16.13.1",
        "react-icons": "^3.11.0",
        "react-router-dom": "^5.2.0",
        "react-scripts": "3.4.3",
        "react-scroll": "^1.8.1",
        "styled-components": "^5.2.0",
        "@types/node": "^15.6.0",
        "jwt-decode": "^3.0.0"
    
    • Slbox
      Slbox almost 3 years
      Can you please edit your question title to match the actual problem at hand? It's far too vague and open-ended as is. The core of your issue is with not being able to contact your API or not being able to read URL search parameters.
    • uberrebu
      uberrebu almost 3 years
      it is not being able to access the search params...did you read question at all? read question first before asking to change it
    • Slbox
      Slbox almost 3 years
      I read it... I said it's about one thing or the other - API access or query parameter reading. Your title, "how do i setup verify account with react?" is a bad title because React doesn't verify accounts at all and the title doesn't actually reference the relevant library or the specific problem you're having
  • Cardoso
    Cardoso almost 3 years
    Can you print the props with console.log and show me the result, please?
  • uberrebu
    uberrebu almost 3 years
    like this? const VerifyAccount = (props) => { const { token, email } = props.match.params console.log({'token': token, 'email': email});
  • uberrebu
    uberrebu almost 3 years
    i have that and nothing is getting logged to console even..so am not even sure what is going on..i only get 200 or 304 status code with no other logs
  • Cardoso
    Cardoso almost 3 years
    I update my answer, can you show me the console log result?
  • uberrebu
    uberrebu almost 3 years
    so i should have it like this? const VerifyAccount = () => { const useQuery = () => new URLSearchParams(useLocation().search); const { token, email } = useQuery(); console.log({'token': token, 'email': email}); is this right?
  • Drew Reese
    Drew Reese almost 3 years
    @uberrebu useQuery should be defined outside the component, but yes.
  • Cardoso
    Cardoso almost 3 years
    And please show me the location. I've updated my answer. Please have a look at it.
  • Cardoso
    Cardoso almost 3 years
  • uberrebu
    uberrebu almost 3 years
    what do you mean outside the component? VerifyAccountPage is a class-based component so you mind posting how everything should look like? i imported intop the App.js file like import VerifyAccountPage from './pages/verifyAccount' ... i update the question to include this piece
  • Drew Reese
    Drew Reese almost 3 years
    @uberrebu Please see the last section of my answer regarding class-based components. React hooks are incompatible with class-based components, so a useQuery hook won't work.
  • uberrebu
    uberrebu almost 3 years
    so what will be the solution to go with?
  • Drew Reese
    Drew Reese almost 3 years
    @uberrebu It seems you've a functional component, so I'd go with the first. If this isn't working then perhaps you've an issue with how you are rendering routes or linking to this path/page.
  • uberrebu
    uberrebu almost 3 years
    yeah i posted most of all i have...page linking looks correct but maybe if you see anything off...first answer...am not even getting anything in console log
  • uberrebu
    uberrebu almost 3 years
    the usequery params from the codesandbox worked..thanks also