-3

I have a functional React component that I want to return a list of information about a car. The first three lines of the return statement (model, maker, release) load with no problem, but the categories won't load because React says 'category' is undefined.

When I console.log car after it is set in state, the car object has the categories key on it, and I can expand that to show three category objects. I can then expand each of those to show category.id and category.name.

So is there a way to access car.categories.category.name? Is the issue that there are three objects?

const CarDetails = () => {
    const {carsId} = useParams();
    const [car, setCar] = useState([])

    const loadCar = () => {
        getOneCar(carsId)
            .then(data => {
                setCar(data)})
    }

    useEffect(() => {
        loadCar()
    }, []);

    useEffect(() => {
        console.log(car)
    }, [car])


    return (
        <>
        <h2>{car.model}</h2>
        <p>Maker: {car.maker}</p>
        <p>Year released: {car.released}</p>
        {/* <p>Categories: {car.categories.category.name}</p> */}
        </>
    )

This is what the object looks like

"model": Corvette
"maker": Chevrolet
"categories": [
            {
                "id": 1,
                "category": {
                    "id": 1,
                    "name": "Sports"
                }
            },
            {
                "id": 2,
                "category": {
                    "id": 2,
                    "name": "Hybrid"
                }
jnpdx
  • 45,847
  • 6
  • 64
  • 94
CodeMonkey
  • 123
  • 7
  • 1
    You need to account for your initial state (which is `[]` right now, but should probably be `undefined` unless you want an array). Right now, you try to render the `car` no matter what -- you should only render if you have a value (which happens after the async call) – jnpdx Jun 12 '22 at 02:14
  • Right, initial value for `car` should be like `null` or `undefined` like @jnpdx said. And you should only render if `car` has a value. Add this line: `if (!car) { return null; }` – Son Nguyen Jun 12 '22 at 02:17

3 Answers3

0

Your car.categories is an array, not an object. You cannot read an array by the dot notation. Instead, you must loop through it to access each element, like this:

<>
  <h2>{car.model}</h2>
  <p>Maker: {car.maker}</p>
  <p>Year released: {car.released}</p>
  <p>Categories: </p>
  <ul>
    {car.categories.map((category) => (
      <li>{category.name}</li>
    ))}
  </ul>
</>
Son Nguyen
  • 1,472
  • 8
  • 16
0

Well, if you look "categories" value, you will see its a list. So you can't access category by doing categories.category.

However, category[0].category.name would work as you need to index the list.

Or you can map the list

categories.map(item => item.category.name)
Buddy Bob
  • 5,829
  • 1
  • 13
  • 44
0

I think car.categories is an array not an object. So car.categories.category does not work. Please try car.categories[0].category, car.categories[1].category, ... like this.

<>
  <h2>{car.model}</h2>
  <p>Maker: {car.maker}</p>
  <p>Year released: {car.released}</p>
  {/* <p>Categories: {car.categories.category.name}</p> */}
  <p>Categories: </p>
  {car && car.categories.map(item => {
    return(<span>{item.category.name}</span>)
  })}
</>

Thanks.