React BrowserRouter: Location is undefined

Viewed 174

I'm trying to pass an object from one component to another using state in location, however, every time I'm trying to read the property of state it writes to me that location is undefined.

Here is my App.tsx

import React, { Component } from "react";
import {BrowserRouter as Router, Redirect, Route} from 'react-router-dom';

import AdminPanel from "./components/admin-panel/admin-panel";
import UserPanel from "./components/user-panel/user-panel";
import OrderForm from "./components/order-form/order-form";
import Login from "./components/login/login";
import OrderSummary from "./components/order-summary/order-summary";
import Header from "./components/header/header";
import UserService from "./services/user-service";
import {LoginData} from "./types/types";

export default class App extends Component {

    //User data information object creation
    userService = new UserService()

    state = {
        isAuthorised: false
    }

    //userService.login() execution if succeed change isAuthorised state on true
    login = async (data: LoginData) => {
        if (await this.userService.login(data)) {
            this.setState({
                isAuthorised: true
            })
        }
    }

    render() {
        const {isAuthorised} = this.state
        const {userData} = this.userService
        const {role, name} = userData

        return (
            <div>
                <Header isAuthorised={isAuthorised} name={name}/>
                <Router>
                    {
                        !isAuthorised && (<Redirect to='/' />)
                    }
                    <Route path="/" render={() => (
                        <Login login={this.login} isAuthorised={isAuthorised} role={role}/>
                    )} exact/>
                    <Route path="/admin-panel" component={AdminPanel} exact/>
                    <Route path="/user-panel" render={() => (
                        <UserPanel isAuthorised={isAuthorised} userData={userData} />
                    )} exact/>
                    <Route path="/order-form" render={() => (
                        <OrderForm {...userData} />
                    )} exact/>
                    <Route path="/order-summary" component={OrderSummary} exact/>
                </Router>
            </div>
        );
    }
}

Here is my component that is passing the data:

import React, {useState} from "react";
import {Link} from "react-router-dom";
import {DefaultValues} from "react-hook-form";
import {FormValues} from "../../../types/types";

type AccordeonItem = {
    title: string,
    data: DefaultValues<FormValues>
}

export const AccordeonItem = ({ title, data }: AccordeonItem) => {
 
    return (
       <div className="p-4 pt-0">
          <p className="text-gray-700">Some text</p>
          <Link to={{ pathname: '/order-form', state: { savedOrder: data} }}>
             Reorder
          </Link>
       </div>
    );
};

And finally, a component that should receive the data:

import React from "react";
import OrderFormElements from "../parts/form-elements/order-form-elements";
import {FormValues, UserData} from "../../types/types";
import CalculatorService from "../../services/calculator-service";
import {RouteComponentProps, withRouter} from "react-router-dom";
import { StaticContext } from 'react-router';
import {DefaultValues} from "react-hook-form";

type LocationState = {
    savedOrder: DefaultValues<FormValues>
}


const OrderForm: React.FunctionComponent<UserData & RouteComponentProps<{}, StaticContext, LocationState>> = (userData: UserData, {location}: RouteComponentProps<{}, StaticContext, LocationState>) =>  {

    const onSubmit = (data: FormValues) => {
        const Calculator = new CalculatorService(userData)
        console.log("Works",data)
    }

    return <OrderFormElements 
                mail={userData.mail} 
                savedOrderData={location.state.savedOrder} 
                onSubmit={onSubmit} />
}

export default withRouter(OrderForm)

So as I said before, here I recieve an error that location is undefined

                mail={userData.mail} 
                savedOrderData={location.state.savedOrder} 
                onSubmit={onSubmit} />

Seems like I'm using the right import from react-router-dom, but still can't solve the problem.

1 Answers

In order to pass props such as history to your route component, you have to use route's render props to do it.

Do the necessary changes in your App.tsx file as follows.

<Route path="/order-form" render={props => (
                        <OrderForm {...props} {...userData} />
                    )} exact/>

And change OrderForm component function parameters as follows to get location prop.

const OrderForm: React.FunctionComponent<UserData & RouteComponentProps<{}, StaticContext, LocationState>> = (userData: UserData, location: RouteComponentProps<{}, StaticContext, LocationState>) =>  {

Hope this would solve your issue.

Related