ReactJS: ошибка типа: не удается прочитать свойство ‘item’ неопределенного

#javascript #reactjs #api

#javascript #reactjs #API

Вопрос:

У меня возникли проблемы с небольшим упражнением с реактивным маршрутизатором

У меня есть файл «ItemDetail.js » в котором я определяю компонент «ItemDetail», который вызывается маршрутом из другого компонента следующим образом: <Route path="/shop/:id" component={ItemDetail}/> . Это мой код:

 import React, {useState, useEffect} from "react";

function ItemDetail({ match }) {

    const [item, setItem] = useState({});
    console.log(match);

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

    
    const fetchItem = async () => {
        const data = await fetch(`https://fortnite-api.theapinetwork.com/item/get?id=${match.params.id}`);
        const item = await data.json();
        setItem(item);
        console.log(item);
    }


    return (
      <div>
          <h3>Item: {item.data.item.name}</h3>
      </div>
  );
}

export default ItemDetail;
 

Идентификатор пути — это идентификатор, который мне нужен для вызова API (более match.params.id ).

Метод fetchItem () извлекает нужные мне данные в виде JSON, затем я сохраняю их в элементе состояния, а затем визуализирую свой материал для рендеринга. Но он выдает ошибку: «Ошибка типа: не удается прочитать свойство’item’ неопределенного» в строке, к которой я обращаюсь item.data.name из JSX.

Странная вещь: когда я переключаюсь <h3>Item: {item.data.item.name} </h3> на <h3>Item: </h3> , а затем возвращаюсь к <h3>Item: {item.data.item.name} </h3> нему, он работает только один раз, и когда я снова обновляю или перехожу по своему сайту к этому пути, он снова выдает эту ошибку

Комментарии:

1. При первоначальном рендеринге item значение установлено только на {} , что означает, что попытка доступа item.data.item приведет к сбою (вы бы пытались получить доступ item undefined ). Одним из распространенных способов избежать этого является отображение чего-либо во время загрузки из fetch вызова: <h3>Item: {item.data ? item.data.item.name : "Loading..."}</h3>

2. Ооо, так это потому, что возвращаемый код выполняется перед fetchItem() ? Спасибо, что сработало для меня

3. Да, fetch это происходит асинхронно, поэтому перед возвратом выборки обязательно выполняется рендеринг, и вы устанавливаете состояние.

Ответ №1:

Вам нужно контролировать его, потому что react рендерится до того, как вы получите item. Вы можете редактировать следующим образом: так что он будет проверять, когда вы получили item, он отобразит страницу.

 import React, {useState, useEffect} from "react";

function ItemDetail({ match }) {

    const [item, setItem] = useState({});
    console.log(match);

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

    
    const fetchItem = async () => {
        const data = await fetch(`https://fortnite-api.theapinetwork.com/item/get?id=${match.params.id}`);
        const item = await data.json();
        setItem(item);
        console.log(item);
    }


    return (
      <div>
         <h3>Item: {item amp;amp; item.data amp;amp; item.data.item ? item.data.item.name : "Loading..."}</h3>
      </div>
  );
}

export default ItemDetail;
 

Также вы можете использовать необязательную цепочку для короткого решения :
<h3>Item: {item?.data?.item ? item.data.item.name : "Loading..."}</h3 >

Комментарии:

1. Да, я забыл об этом, вы правы. Я редактирую код.

2. Также я добавил проверки item и item.data и item.data.item, так что это будет лучшая проверка, не так ли?

3. Да. На самом деле другим гораздо более простым вариантом, если доступна дополнительная цепочка, было бы просто сделать что-то вроде этого: item?.data?.item?.name || "Loading..."

4. Я знаю, что, возможно, оно недоступно, поэтому я добавил другой способ решения. Но это возможно.