0

I'm trying to pass a prop through a React Router Link Component, however when declaring useLocation hook that comes with the React Router in my class component:

const location = useLocation()
const { from } = location.state

I get this error React Hook "useLocation" cannot be called in a class component. React Hooks must be called in a React function component or a custom React Hook function Would it be possible to use useLocation in my class Component, or would I have to convert to a functional component ?

Here is my app Structure:

My functional component using the React Router Link Component to pass in a prop to my class component:

import { Button } from '@mui/material';
import React from 'react'
import { Link, useLocation } from 'react-router-dom';
import icon from './images/icon.png';
import Main from './Main';
import Screen from './Screen';

const Success = ({ nextStep, handleChange, values, props }) => {
    // ...
    
    const current = new Date();
    const date = `${current.getDate()}/${current.getMonth()+1}/${current.getFullYear()}`;
  
    // ...

    return(
       
            <div>
                <p>You have successfully bought: </p>
                <p>{`${values.payAmount}`}  BTC on {date}</p>

                <Link to='/App' state={{ from: values.payAmount }}>
                    <Button color="primary"
                    variant="contained"
                    style={{ padding:'9px 60px'}}
                    >Done</Button>
                </Link>
            </div>
    )
}

export default Success;

My class component using the useLocation hook in order to receive data: (this is where I get the error)

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

class Main extends React.Component {
  render() {
    const location = useLocation()
    const { from } = location.state
    
    return (
        <div >
          <h1> My Accounts </h1>
          <p> You know have {from} in your wallet. </p>
      </div>
    )
  }
}

export default withStyles(styles, { withTheme: true })(Main);
Dave Newton
  • 158,873
  • 26
  • 254
  • 302
alyssa
  • 9
  • 1
  • 2
  • 3
    You cannot use hooks in class components. [React docs](https://reactjs.org/docs/hooks-faq.html#:~:text=You%20can't%20use%20Hooks,implementation%20detail%20of%20that%20component.). You probably have to use a wrapper component (function). – Palladium02 Aug 23 '22 at 16:03
  • 1
    To add on the first comment, you can always use a HOC or pass it as a prop from the parent component, which can be a functional component that uses the useLocation hook. – jean182 Aug 23 '22 at 16:06

2 Answers2

2

Hooks cannot be used in class components and React Router v6 has no alternative for class components. You need to walkaround it somehow. For example you can create another functional component as a wrap. Something like:

const LocationComponent = props => {
  const location = useLocation()
  return <Main location={location} {...props} /> // your component
}
Jax-p
  • 7,225
  • 4
  • 28
  • 58
0

The react-router docs actually cover your case: https://reactrouter.com/en/6.6.1/start/faq

Simply copy the example wrapper and put it in a js file and then import it.

import {
  useLocation,
  useNavigate,
  useParams,
} from "react-router-dom";

function withRouter(Component) {
  function ComponentWithRouterProp(props) {
    let location = useLocation();
    let navigate = useNavigate();
    let params = useParams();
    return (
      <Component
        {...props}
        router={{ location, navigate, params }}
      />
    );
  }

  return ComponentWithRouterProp;
}
Jeremy Thompson
  • 61,933
  • 36
  • 195
  • 321
timotgl
  • 2,865
  • 1
  • 9
  • 19