Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

React: Uncaught TypeError: Cannot read properties of undefined (reading '0')

I need to use this information for my purchase completed page, but i get this error:
Uncaught TypeError: Cannot read properties of undefined (reading ‘0’)

My code is:

import { getFirestore } from "../firebase/firebase";
import { useParams } from "react-router-dom";

function ConfirmacionCompraPage() {

  const {orderId} = useParams();
  const [order, setOrder] = useState({});

  useEffect(() => {
    const db = getFirestore();
    db.collection("ordenes")
    .doc(orderId)
    .get()
    .then((res) => setOrder({ id: res.id, ...res.data() }));
  }, [orderId]);

  return (
    <div>
      <h2>Detalle de su compra: {order.items[0].item.paleta}</h2>
    </div>
  );
};

export default ConfirmacionCompraPage ;```


And my Firestore is:
[![Firestore][1]][1]


  [1]: https://i.stack.imgur.com/cGdST.png

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

>Solution :

The initial state of order is an empty object:

const [order, setOrder] = useState({});

So order.items is undefined, and order.items[0] is an attempt to read index 0 of undefined.

You could set some initial state:

const [order, setOrder] = useState({ items: [{ item: { paleta: '' }}]});

Or perhaps use null checking (if it works with array indexing? I’m actually not certain at the moment):

<h2>Detalle de su compra: {order?.items?[0]?.item?.paleta}</h2>

Or perhaps conditionally render:

{
  (order && order.items && order.items.length > 0 && order.items[0].item)
    ? <h2>Detalle de su compra: {order?.items?[0]?.item?.paleta}</h2>
    : null
}

Any way you approach it, the main point here is that you’re drilling very deep into an object without checking if that object has any of the properties you’re using.


You might also simplify any of the above by only keeping the value paleta in state instead of the entire order object, if you only actually need that one value. So the state would be something like:

const [paleta, setPaleta] = useState('');

And you’d drill into the properties when setting it:

.then((res) => setPaleta(res.data().items[0].item.paleta));

And reference it more simply in rendering:

<h2>Detalle de su compra: {paleta}</h2>

Of course this is only if you’re just using that one value. If this example is reduced for brevity and you actually need much more of the object then, yes, keep the whole object in state. But logically apply null checking in the rest of your rendering to make sure the object is populated before rendering it.

Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading