Home > Net >  React router useHistory is undefined
React router useHistory is undefined

Time:10-05

After submitting save button React throws an error like this => Cannot read properties of undefined (reading 'push')

The Routes and Links are in the separate components. The Code is following in AdminEdit.jsx

import { Button, Form } from "antd";
import React, { useEffect } from 'react'
import { useParams,  useHistory } from 'react-router';
import AntdCheckbox from '../../Components/AntdChechBox';
import ButtonPrimary from '../../Components/ButtonPrimary';
import FormContainer from '../../Components/FormContainer';
import InputFormText from '../../Components/InputFormText';
import SecondaryButton from '../../Components/SecondaryButton';
import PageEdit from '../../Layouts/PageTypes/PageEdit';
import BackEndActions from '../../Utils/BackEndActions';
import { notifySuccess } from "../../Utils/Notifications";

const AdminEdit = (props) => {
    let { idAdmin } = useParams();
    const { history } = useHistory()
    const [form] = Form.useForm();
    useEffect(async () => {

        const result = await BackEndActions.getSingleAdmin(idAdmin)
        console.log(result)
        if (result.success) {
            form.setFieldsValue({
                ...result.data
            })
        }
    }, []);

    const onFinish = async (values) => {
        console.log(values, "val")
        const d = new Date();
        const params = {
            createDate: d,
            email: values.email,
            firstName: values.firstName,
            idAdmin: idAdmin,
            lastName: values.lastName,
            password: "",
            phone: values.phone,
            role: 2,
            sendEmail: 0,
            status: 1,
            updateDate: null
        }
        const result = await BackEndActions.saveAdmin(params)
        console.log(result)
        if (result.success) {
            **history.push("/country/list")**
            notifySuccess("success")
        }
    }


    return (
        <PageEdit>
            <FormContainer
                form={form}
                onFinish={onFinish}
                name="EditAdmin"
            >
                <InputFormText
                    label="First Name"
                    name="firstName"
                    required

                />
                <InputFormText
                    label="Last Name"
                    name="lastName"
                />

                <InputFormText
                    label="Phone"
                    name="phone"
                />

                <InputFormText
                    label="Email"
                    name="email"
                />
                <AntdCheckbox />
                <ButtonPrimary
                    label="Save"

                />
                <SecondaryButton
                    label="Cancel"

                />
            </FormContainer>

        </PageEdit>
    );
}

export default AdminEdit;

I even wrapped the component with withRouter but no changes

The code in the Routes.jsx are following

            <PrivateRoute path="/admin/list"
                render={(props) => {
                    return (
                        <MainLayout title="Admins">
                            <AdminPage />
                        </MainLayout>
                    )
                }}
            />
            <PrivateRoute path="/admin/edit/:idAdmin"
                render={(props) => {
                    return (
                        <MainLayout title="Admin">
                            <AdminEdit {...props} />
                        </MainLayout>
                    )
                }}
            />

The Index.js component is wrapped in BrowserRouter.What i did wrong?

CodePudding user response:

Just remove the destructuring

const history = useHistory();

As a side note, as you posted that you tried passing the component to the render props:

<PrivateRoute path="/admin/edit/:idAdmin"
  render={(props) => {
     return (
        <MainLayout title="Admin">
           <AdminEdit {...props} />
         </MainLayout>
     )
  }}
/>

This means that you will have access to history, match, and location from the props object in <AdminEdit />. So it's another way of achieving the same goal. Choose one or the other. Personally, I feel that using the useHistory hook is more convenient when the component that requires access to history is not a direct child of a Route component.

CodePudding user response:

the useHistory hook returns the history object directly it doesn't return an object that contains { history } as a property

const history = useHistory(); 

reference here

  • Related