'I want pass book data to the view page to the edit page in react js

I used the prop method but the chrome console said this error TypeError: Cannot read properties of undefined (reading 'props') this is the my whole code of the book details view page

  import React,{ useEffect, useState } from 'react'
    import axios from "axios";
    import { variables } from "../../../Veriables";

    const ManageBookView =() => {
    const [book, setBook]= useState([])


    const getData = async () =>{
        try{
            const data = await axios.get(variables.API_URL+"book")
            console.log(data.data);
            setBook(data.data)
        }
        catch(e){
            console.log(e)
        }
    }

    
  

    useEffect(()=>{
        getData()
    },[])



    async function  deleteClick (id) {
      if(window.confirm('Are you sure ?')){
        let result = fetch(variables.API_URL+'book/'+id,{
            method:'DELETE'
        });
        result = await (await result).json;
        alert('Book Deleted Successfully!')
        getData();
      }
    }


    const editCick = (id) =>{
      this.props.history.push({
        pathname:'/managebookedit/'+id
      })
    }

    return (
    <div>
         {/* Content Wrapper. Contains page content */}
         <div className="content-wrapper">
         
         <div className="content-header">
        <div className="container-fluid">
      <div className="row mb-2">
        <div className="col-sm-6">
          <h1 className="m-0">Book</h1>
        </div>{/* /.col */}
        <div className="col-sm-6">
          <ol className="breadcrumb float-sm-right">
            <li className="breadcrumb-item"><a href="/paneladmin">Home</a></li>
            <li className="breadcrumb-item active">Manage Book</li>
          </ol>
        </div>{/* /.col */}
      </div>{/* /.row */}
    </div>{/* /.container-fluid */}
  </div>
            <section className="content">
             <div className="container-fluid">
    <div className="row">
      <div className="col-12">
        <div className="card">
          <div className="card-header">
            <h3 className="card-title">   Manage Book</h3>
            <div className="card-tools">
            <a href="/managebookadd"><button type="button" className="btn btn-block btn-outline-primary btn-sm">        Add Book
                </button></a>
                
            </div>
          </div>
          {/* /.card-header */}
          <div className="card-body table-responsive p-0" style={{height: 500}}>
            <table className="table table-hover text-nowrap">
              <thead>
                  
                <tr>
                  <th>Book ID</th>
                  <th>Title</th>
                  <th>Author</th>
                  <th>Category</th>
                  <th>Availability</th>
                </tr>
              </thead>
              <tbody>
              {book.map((item) =>{
                  return(
                        <tr key={item.book_id}>
                        <td>{item.book_id}</td>
                        <td>{item.book_title}</td>
                        <td>{item.book_author}</td>
                        <td>{item.book_category}</td>
                        <td>{item.book_availability}</td>
                        <td> <button type="button" class="btn btn-block btn-light btn-sm"
                        onClick={()=>editCick(item.book_id)}>Edit</button> </td>
                        <td><button type="button" class="btn btn-block btn-danger btn-sm"
                        onClick={()=>deleteClick(item.book_id)}>Delete</button></td>
                        </tr>
                    )
                })}
              </tbody>
            </table>
          </div>
          {/* /.card-body */}
        </div>
        {/* /.card */}
      </div>
    </div>
    {/* /.row */}
    </div>
                            
    </section>
    </div>       
    </div>
    )
    }
    export default ManageBookView;

I cannot find what is the error of the code, this is the my edit page code how I can pass the the data to the this page

import React, {useState, useEffect} from 'react';
import axios from 'axios';
import { variables } from '../../../Veriables';

const ManageBookEdit = (props) => {
    const [book, setBook] = useState({title:'',author:'',category:'',releasedate:'',price:'',description:'',type:'' })
    const [title, setTitle] = useState('')
    const [author, setAuthor] = useState('')
    const [category, setCategory] = useState('')
    const [releasedate, setReleasedate] = useState('')
    const [price, setPrice] = useState('')
    const [description, setDescription] = useState('')
    const [type, setType] = useState('')
    const url = variables.API_URL+'book/Getbook/'+props.match.param.id;


    const getData = async () =>{
        try{
            const data = await axios.get(url)
            console.log(data.data);
            setBook(data.data)
        }
        catch(e){
            console.log(e)
        }
    }

    useEffect(()=>{
        getData()
    },[])

  return (
    <div>
    {/* Content Wrapper. Contains page content */}
    <div className="content-wrapper">
      {/* Content Header (Page header) */}
      <section className="content-header">
        <div className="container-fluid">
          <div className="row mb-2">
            <div className="col-sm-6">
              <h1>Book Add</h1>
            </div>
            <div className="col-sm-6">
              <ol className="breadcrumb float-sm-right">
                <li className="breadcrumb-item"><a href="/paneladmin">Home</a></li>
                <li className="breadcrumb-item"><a href="/managebook">Book Manage</a></li>
                <li className="breadcrumb-item active">Book Add</li>
              </ol>
            </div>
          </div>
        </div>{/* /.container-fluid */}
      </section>
      {/* Main content */}
      <section className="content">
        <div className="row">
          <div className="col-md-12">
            <div className="card card-primary">
              <div className="card-header">
                <h3 className="card-title">Book</h3>
                <div className="card-tools">
                  <button type="button" className="btn btn-tool" data-card-widget="collapse" title="Collapse">
                    <i className="fas fa-minus" />
                  </button>
                </div>
              </div>
              <div className="card-body">
                <div className="form-group">
                  <label htmlFor="inputName">Title</label>
                  <input type="text" id="inputName" className="form-control" 
                  value={book.title}
                  />
                </div>
                <div className="form-group">
                  <label htmlFor="inputName">Author</label>
                  <input type="text" id="inputName" className="form-control" 
                  value={book.author}
                  />
                </div>
                <div className="form-group">
                  <label htmlFor="inputName">Category</label>
                  <input type="text" id="inputName" className="form-control" 
                  value={book.category}
                  />
                </div>
                <div className="form-group">
                  <label htmlFor="inputName">Release Date</label>
                  <input type="date" id="inputName" className="form-control" 
                  value={book.releasedate}
                  />
                </div>
                <div className="form-group">
                  <label htmlFor="inputName">Price</label>
                  <input type="number" id="inputName" className="form-control" 
                  value={book.price}
                  />
                </div>
                <div className="form-group">
                  <label htmlFor="inputDescription">Description</label>
                  <textarea id="inputDescription" className="form-control" rows={4} defaultValue={""} 
                  value={book.description}
                  />
                </div>
                <div className="form-group">
                  <label htmlFor="inputStatus">Type</label>
                  <select id="inputStatus" className="form-control custom-select"
                  value={book.type}
                  >
                    <option selected disabled>Select one</option>
                    <option value="2" key="2" >Digital</option>
                    <option value="1" key="1" >Printed</option>
                  </select>
                </div>
              </div>
              {/* /.card-body */}
            </div>
            {/* /.card */}
          </div>
        </div>
        <div className="row">
          <div className="col-12">
            <a href="#" className="btn btn-secondary">Cancel</a>
            <button type="button" className="btn btn-success float-right" 
             >Create</button>
          </div>
        </div>
        <br/>
      </section>
      {/* /.content */}
    </div>
    {/* /.content-wrapper */}
        </div>
  )
}

export default ManageBookEdit

this is the error log

enter image description here



Solution 1:[1]

So you are trying to access props.match... and props.history... in your code. This only works if the Compent is called/accessed via <Route> component from react-router.

I suspect you have a parent Component that looks somewhat like this.

const Parent = () => {
  return(
   <>
     <ManageBookView/>
     <ManageBookEdit/>
   </>
  )
}

But what you really need is like this:

const Parent = () => {
  return(
   <Router>
      <Route path="managebookedit" component={ManageBookView}/>
      <Route path="managebookedit/:id" component={ManageBookEdit}/>
   </Router>
  )
}

Since you only show the Component themselves and not how they are used, its hard to tell for sure, but probably the error is there.

Check out the react-router documentation on how to qualify a component to use the props you want to use.

Solution 2:[2]

Issue

Uncaught TypeError: Cannot read properties of undefined (reading 'props')
    at editCick (ManageBookView.js:42:1)
    at onClick (ManageBookView.js:106:1)
    ... and so on in stacktrace

This error is informing you that the code is attempting to access props from an undefined object, accessing this.props throws the error. Not only is ManageBookView a React function component, meaning that there is no defined this to access a props object from, but you've also not provided any props object to the component.

const ManageBookView = () => { ... }

In other words, even if this was defined, props is also undefined, so props.history would throw a similar error.

Solution

Provide the props object to your ManageBooView component.

Instead of

const ManageBookView = () => { ... }

use

const ManageBookView = (props) => { ... }

Ensure that this ManageBookView component is actually receiving the route props (history, location, and match). This is accomplished when ManageBookView is:

  • Rendered directly by a route component

     <Route path="...." component={ManageBookView} />
    
  • Decorated with the withRouter Higher Order Component

     export default withRouter(ManageBookView);
    

Now there is a defined history prop.

const ManageBookView = (props) => {
  ...

  const editClick = (id) => {
    props.history.push({
      pathname: '/managebookedit/' + id
    });
  }

  ...
};

Alternatively you can forego the props object (if it's not referenced elsewhere) and use the React hooks directly.

Example:

import { useHistory } from 'react-router-dom';

const ManageBookView = () => {
  const history = useHistory();

  ...

  const editClick = (id) => {
    history.push({
      pathname: '/managebookedit/' + id
    });
  }

  ...
};

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Laurenz Honauer
Solution 2 Drew Reese