uberrebu
uberrebu

Reputation: 4349

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

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"

Upvotes: 6

Views: 53754

Answers (3)

Drew Reese
Drew Reese

Reputation: 203466

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.

Upvotes: 14

GMKHussain
GMKHussain

Reputation: 4709

React JS

http://localhost:3000/#/product?id=159
import React from "react";
import { useLocation } from "react-router-dom";

const MyComponent = () => {
  const myParam = useLocation().search;
  const productId= new URLSearchParams(search).get("id");
  console.log(productId); // 159
}

Vanilla JavaScript

const siteUrl = window.location.search;
const urlParams = new URLSearchParams(siteUrl);
console.log( urlParams['id'] ) // 159

Upvotes: 2

Cardoso
Cardoso

Reputation: 1088

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.

Upvotes: 8

Related Questions