Search code examples
javascriptreactjsjsonobjectnested

How can I access JSON nested obj to set state and display in React JSX?


I'm fetching a JSON object from my REST API @ "localhost:3001/customers/id" and trying to set it as state but I'm having trouble accessing my nested objects when trying to display the contents in my JSX.

import { React, useState, useEffect } from "react";
import { useParams } from "react-router-dom";
import './CustomerItem.css'

const CustomerItem = () => {
    const { id } = useParams()
    const [customer, setCustomer] = useState([])
    const [isLoaded, setIsLoaded] = useState(false)

    useEffect(() => {
        fetch(`http://localhost:3001/customers/${id}`)
        .then((response) => response.json())
        .then((data) =>
            setCustomer(data),
            setIsLoaded(!isLoaded)
        )
    }, [id])

    if (!isLoaded) return <h1>Please refresh...</h1>
     
    return (
         <div> 
             <h1> {customer.customerInfo.name} </h1>
             <h3> {customer.vehicleInfo.year} {customer.vehicleInfo.make} {customer.vehicleInfo.model} </h3>
         </div>
    )
}
export default CustomerItem
  
{
   "id": 1,
   "customerInfo": {
      "name": "Samara Grant",
      "phone": "347-555-5555",
      "email": "[email protected]",
      "address": "123 Spring St New York, NY 11001"
   },
   "vehicleInfo": {
      "year": "2018",
      "make": "BMW",
      "model": "M4",
      "mileage": "18,564",
      "vin": "WBS3R9C50FK331665",
      "plateNumber": "M4DEULK"
   },
   "repairOrders": [
      {
         "id": 100,
         "dateOfService": "03/12/2023",
         "customerConcern": "Customer states intermittent whistling sound coming from bonnet. Only after vehicle is warm and @ idle",
         "technicianDiagnosis": "Upon test drive audible whistling noise persists. Located @ PVC Valve in valve cover. Valve cover needs to be replaced",
         "partsOrdered": "Qty: 1x - Part#11127846359 | S55 Valve Cover",
         "serviceAdvisor": "JL",
         "technician": "06"
      },
      {
         "id": 101,
         "dateOfService": "03/29/2023",
         "customerConcern": "Customer states oil leak coming from engine",
         "technicianDiagnosis": "Upon inspection oil leaking from valve cover. Valve cover appears to be unwarped. Gasket will need replacing.",
         "partsOrdered": "Qty: 1x - Part#11127587804 | S55 Valve Cover Gasket Seal",
         "serviceAdvisor": "JL",
         "technician": "06"
      }
   ]
}

When I console.log(data) I am able to see the entire object and it's nested object info coming through. When I try to map through the object in JSX to access the nested data it won't allow it since it's not an array. And Using string literals as seen below gives me

TypeError: Cannot read properties of undefined (reading 'year')

Solution

  • React will "batch" state updates if they are triggered in the same function. Basically you'll need to update your code so that react knows that calling setCustomer and setIsLoaded needs to happen at the same time.

    You can find more details in the React docs: https://react.dev/learn/queueing-a-series-of-state-updates

    Try replacing :

    .then((data) =>
      setCustomer(data),
      setIsLoaded(!isLoaded)
    )
    

    with :

    .then((data) => {
          setCustomer(data);
          setIsLoaded(!isLoaded);
    })