sohanur shanto
sohanur shanto

Reputation: 93

How to solve react typeError: Cannot read properties of undefined (reading 'name')

Here I am trying to make a crud operation. Everything is working until when I try to update something by their id then it is showing me this error. For the first one in my attached screenshot I am able to update data but when I try to update the other one it is showing me this error at selectVendor function.

#this is my code

   import React, { useEffect, useState } from 'react'
import { useDispatch, useSelector } from 'react-redux'
import axios from 'axios'
import { Link } from 'react-router-dom'
import { Form, Button, Table } from 'react-bootstrap'
import Loader from '../components/Loader'
import Message from '../components/Message'
import Paginate from '../components/Paginate'

function VendorScreen() {
    const [vendors, setVendor] = useState([])
    const [name, setName] = useState("");
    const [userName, setUserName] = useState("");
    const [address, setAddress] = useState("");
    const [profile_picture, setPicture] = useState("");
    const [vendorId,setVendorId]=useState(null)
    const [uploading, setUploading] = useState(false)
    

    const userLogin = useSelector(state => state.userLogin)
    const { userInfo } = userLogin
  
    useEffect(() => {
      getVendors();
    }, [])
    function getVendors() {
      fetch("http://localhost:8000/api/orders/vendors/",{
      method: 'GET',
        headers:{
          'Accept':'application/json',
          'Content-Type':'application/json',
          "Authorization" : `Bearer ${userInfo.token}`,
        },}).then((result) => {
          
          
        result.json().then((resp) => {
          console.warn(resp)
          setVendor(resp)
          setName(resp[0].name)
          setAddress(resp[0].address)
          setVendorId(resp[0].id)
          setPicture(resp[0].profile_picture)
          setUserName(resp[0].user.name)
        })
      })
    }
  
    function deleteVendor(id) {
      fetch(`http://localhost:8000/api/orders/delete/${id}`, {
        method: 'DELETE',
        headers:{
            'Accept':'application/json',
            'Content-Type':'application/json',
            "Authorization" : `Bearer ${userInfo.token}`,
        }
      }).then((result) => {
        result.json().then((resp) => {
          console.warn(resp)
          getVendors()
        })
      })
    }

    
    function selectVendor(id) {
      const item = vendors.find(vendor => vendor.id === id);
    
      console.log(item);
    
      if (item) {
        setName(item.name);
        setAddress(item.address);
        setPicture(item.profile_picture);
        setUserName(item.user?.name); // <-- guard if user is undefined/null
        setVendorId(item.id);

      }
    }


    function updateVendor()
    {
      const formData = new FormData();

          formData.append('File', profile_picture);

      let item={name,address, profile_picture}

      console.warn("item",item)
      fetch(`http://localhost:8000/api/orders/update/${vendorId}`, {
        method: 'PUT',
        headers:{
          'Accept':'application/json',
          'Content-Type':'application/json',
          "Authorization" : `Bearer ${userInfo.token}`,
        },
        body:JSON.stringify(item)
      }).then((result) => {
        result.json().then((resp) => {
          console.warn(resp)
          getVendors()
        })
      })
    }


    const uploadFileHandler = async (e) => {
      const file = e.target.files[0]
      const formData = new FormData()

      formData.append('profile_picture', file)
      formData.append('vendor_id', vendorId)

      setUploading(true)

      try {
          const config = {
              headers: {
                  'Content-Type': 'multipart/form-data',
                  "Authorization" : `Bearer ${userInfo.token}`,
              }
          }

          const { data } = await axios.post('/api/products/upload/vendor/', formData, config)


          setPicture(data)
          setUploading(false)

      } catch (error) {
          setUploading(false)
      }
  }

    return (
      <div className="App">
        <h1>Update User Data With API </h1>
        <Table striped bordered hover responsive className='table-sm'>
          <tbody>
            <tr>
              <td>ID</td>
              <td>Name</td>
              <td>Address</td>
              <td>User</td>
              <td>Picture</td>
              <th></th>
              
            </tr>
            {
              vendors.map((item, i) =>
                <tr key={i}>
                  <td>{item.id}</td>
                  <td>{item.name}</td>
                  
                  <td>{item.address}</td>
                  <td>{item.user.name}</td>
                  <td>{item.profile_picture}</td>
                  <td><button variant='danger' className='btn-sm' onClick={() => deleteVendor(item.id)}><i className='fas fa-trash'></i></button>
                  <button variant='info' className='btn-sm' onClick={() => selectVendor(item.id)}><i className='fas fa-edit'></i></button></td>
  
                </tr>
              )
            }
          </tbody>
          </Table>
          <Paginate pages={pages} page={page} isAdmin={true} />
        <div>

            <br ></br>
            <br ></br>
            <br ></br>
            <br ></br>
        <input type="text" value={name} onChange={(e)=>{setName(e.target.value)}} /> <br /><br />
          <input type="text" value={address} onChange={(e)=>{setAddress(e.target.value)}}  /> <br /><br />
          <Form.Control
                                    type='file'
                                    id='image-file'
                                    label='Choose File'
                                    custom
                                    onChange={uploadFileHandler}
                                >

                                </Form.Control>
                                {uploading && <Loader />}
        
           <button onClick={updateVendor} >Update User</button>  
        </div>
      </div>
    );
  }

export default VendorScreen

Do I need to call an api for getbyId something? I followed a tutorial they were able to do that but I don't know how

this is my screenshot

enter image description here

Upvotes: 2

Views: 3774

Answers (1)

Drew Reese
Drew Reese

Reputation: 202605

While vendors is an array, I don't think it's likely the id properties are actually array indices. In the least it doesn't seem like something you should count on being true all the time.

function selectVendor(id) {
  let item=vendors[id-1]; // <-- item likely undefined

  console.log(item.name)
  setName(item?.name)
  setAddress(item?.address)
  setUserName(item?.user.name);
  setVendorId(item?.id);
}

You probably want to search the vendors array for the matching vendor object by id. Array.prototype.find returns undefined if no elements are found via the predicate function, so the code should handle this case appropriately.

Example:

function selectVendor(id) {
  const item = vendors.find(vendor => vendor.id === id);

  console.log(item);

  if (item) {
    setName(item.name);
    setAddress(item.address);
    setUserName(item.user?.name); // <-- guard if user is undefined/null
    setVendorId(item.id);
  }
}

Upvotes: 2

Related Questions