I don't know why my HTTP ( PUT request) is not working in React.js

I’m performing a CRUD operation by adding data in db.json server file.
My edit request is not working like I’m using a Class component and having Error ::

App.js

import React, { useState, useEffect } from 'react';
import {BrowserRouter as Router, Switch,Route} from 'react-router-dom'
import axios from 'axios';
import Header from './components/header';
import DisplayList from './components/displayList';
import InputForm from './components/InputForm';
import EditContacts from './components/editContacts';
import './App.css';

function App() {
  const [contacts,setContacts] = useState([]);

  const getContacts = async ()=>{
    try{
      const res = await axios.get("http://localhost:4000/contacts");
      setContacts(res.data)
    } 
    catch(err){
      console.log(err);
    }
  }

  const addingContacts = async (contact)=>{
    const request = {...contact}
    const response = await axios.post("http://localhost:4000/contacts",request)
    setContacts([...contacts,response.data]);
  }

  const removeContacts = async(id) =>{
   await axios.delete(`http://localhost:4000/contacts/${id}`);
  const newContacts = contacts.filter(contact=> contact.id !== id);
    setContacts(newContacts);
  }
 
//Edit and Update function:
  const updatingContacts = async(contact)=>{
   const response = await 
      axios.put(`http://localhost:4000/contacts/${contact.id}`,contact);
    const {id,Username,Email} = response.data;
    console.log(response.data); 
    setContacts(contacts.map(contact=>{
      return contact.id !== id ? {...response.data} :contact
    }))
  }
  useEffect(()=>{
    getContacts();
  },[])
  
  return (
    <Router>
      <Switch>
        <div className="App">
          <Route path="/" exact>
          <Header/>
          </Route>
          <Route path="/add">
          <InputForm addingContacts={addingContacts}/>
          </Route>
          <Route path="/diplay">
          <DisplayList  contacts={contacts} removeContacts={removeContacts}/>
          </Route>

          <Route path="/edit">
          <EditContacts updatingContacts={updatingContacts}/>
          </Route>
        </div>
      </Switch>
    </Router>
  );
}

export default App;

(editContact.js)Edit Component:

import React, { Component } from 'react';
import{Link} from 'react-router-dom';
import { Form, Button, FormGroup, FormControl, ControlLabel } from "react-bootstrap";

class editContacts extends Component {
    constructor(props) {
        super(props)
       const {id,Username,Email} = props.location.state.contact
        this.state = {
             id,
             Username,
             Email
        }
    }
    handleUpdate=(e)=>{
        e.preventDefault();
        if(!this.state.Username  && !this.state.Email){
            return alert("Input Fields are Empty");
        }
        else{
            alert(`My name is: ${this.state.Username} and my Email address is: ${this.state.Email}`);
        }
        this.props.updatingContacts(this.state);
        this.setState({Username:"",Email:""})
    }
    
    render() {
        return (
            <div>
            <div className="card" >
                 <div className="card-header text-center">
                 <h2>Add Contacts</h2>
                </div>
            </div>
            <Form onSubmit={this.handleUpdate}>
                
            <Form.Group className="mb-3" controlId="formBasicName">
                    <Form.Label>Name</Form.Label>
                    <Form.Control type="text" placeholder="Name" name="Username"value ={this.props.state.Username} onChange={(e)=>{this.setState({Username:e.target.value})}}/>
                </Form.Group>

                <Form.Group className="mb-3" controlId="formBasicEmail">
                    <Form.Label>Email address</Form.Label>
                    <Form.Control type="email" placeholder="Enter email" name="Email" value ={this.props.state.Email} onChange={(e)=>{this.setState({Email:e.target.value})}}/>
                </Form.Group>

                <Button variant="btn btn-outline-success" type="submit" style={{marginBottom:"20px", marginRight:"8px"}}>
                    Update
                </Button>
                <Link to="/">
                <Button variant="btn btn-outline-secondary" type="button" style={{marginBottom:"20px"}}>
                    Main Page
                </Button>
                </Link>
            </Form>
                
            </div>
        )
    }
}

export default editContacts

“Error is occuring in Edit component” Please lemme know if anyone understand this error.

Why do people always assume that it is a problem with React?

That first error has nothing to do with React (not directly at least) - it is a JS error:

TypeError: Cannot read property ‘state’ of undefined

That is telling you that on this line:

const {id,Username,Email} = props.location.state.contact

it can’t find “state” because props.location is undefined. And there is a hard rule in JS that you cannot try to access a property of null or undefined. (Technically you can’t do it for any other primitive, but there are effectively protections in place for the others.)

In your constructor, why not see what props is:

class editContacts extends Component {
    constructor(props) {
        super(props)
        console.log('props in constructor:', props);
        // ...

And while you’re at it, the class name should begin with a capital letter. In JS, classes are expected to be in PascalCase. And in React, components are expected to be in PascalCase, too.

1 Like

@kevinSmith … I’m just started React from couple a weeks ago and after doing some basics, I started performing CRUD and I’m stuck in (Editing and Updating the data) cause I took this part from somewhere else… Can you please help in this ??

I felt like I did help. I identified why the error is happening and even offered advice on how to understand what is happening.

To put it more bluntly, where do you think props.location.state.contact is coming from? There are only two ways for something to get on props in React (afaik): by being passed in from the parent or by being added on with an HOC (e.g., the one returned by connect).

You need to trace back and see where you expect that value to come from and figure out why it doesn’t work.

I assume it is React Router location you are using. If so it has to be this.props.location. I would also assume you are actually passing some state in a Link or Redirect somewhere?

IC, that makes some sense. But again, I think logging out what props is in the constructor would be helpful.

@kevinSmith Agree, you should treat your code like that creepy The Police song Every Breath You Take. Watch it, and do not trust it.

Side note. I know it sounds like a love song, but listen to the actual lyrics…it’s sinister. Also, it hurts like hell to play on the guitar so that is very fitting.

1 Like

@kevinSmith @lasjorg Thank you so much both of you :fist_right: :fist_left:
I figured out the problem !!! :grinning: :grinning: :grinning: :grinning:

1 Like

@billy.s56 Do you want to share so we can all learn? What did the problem turn out being?

So there is a display component where all my list displays …

code:

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

const  displayList = (props) => {
    
    const  delContact=(id)=>{
        props.removeContacts(id);
        alert("Item is successfully removed");
    }
 
const returnList = props.contacts.map((contact)=>{
    return (
        <> 
            <tr>
                <th>{contact.id}</th>
                <td>{contact.Username}</td>
                <td>{contact.Email}</td>
                <td>
                <Link to={{pathname:"/edit", state:{contact:contact}}}>
                <button className="btn btn-outline-primary" style={{ marginRight: "7px" }}><i className="bi bi-pencil-square"></i></button>
                </Link>
                <button className="btn btn-outline-danger" onClick={()=>delContact(contact.id)}><i className="bi bi-trash-fill"></i></button>
                </td>
            </tr>
          
        </>
        );
    });

    return (
    <div>
       <div className="card" >
        <div className="card-header text-center">
          <h2>Contact List</h2>
        </div>
      </div>
        <table className="table table-border table-bordered table-striped text-center">
        <thead>
            <tr>
            <th>#</th>
            <th>Name</th>
            <th>Email</th>
            <th>Action</th>
            </tr>
        </thead>
          <tbody>{returnList}</tbody>
        </table>
        <Link to="/">
        <button className="btn btn-outline-secondary">Main Page</button>
        </Link>
    </div>
       
)
}

export default displayList

So as you said @kevinSmith logging out the things :slight_smile: … so I try this in every component where I pass the props from parent component …
In this line:

<Link to={{pathname:"/edit", state:{contact:contact}}}>
                <button className="btn btn-outline-primary" style={{ marginRight: "7px" }}><i className="bi bi-pencil-square"></i></button>
                </Link>

When I logged the state it seems undefine(no object exist in the state) cause I was doing like this:

state:{contact:props.contact}

That’s why the state seems undefined…

1 Like

This topic was automatically closed 182 days after the last reply. New replies are no longer allowed.