#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. Я знаю, что, возможно, оно недоступно, поэтому я добавил другой способ решения. Но это возможно.