#reactjs #typescript #react-typescript
Вопрос:
Я пытаюсь показать список элементов, которые я получаю от API в бэкэнде. Однако, когда я пытаюсь отобразить массив, в нем не отображается ни один элемент. Что я делаю не так? Кто-нибудь может помочь, пожалуйста?
Я попытался войти в консольный журнал, и я вижу список правильно выбранных элементов. Также отображается тег h2. но не результаты .map.
Это и есть код:
interface Props { products: Product[] | []; } const ProductsList = ({ products }: Props) =gt; { useEffect(() =gt; { getProducts(); console.log('fetched data', getProducts()); }, []); return ( lt;RootContainergt; lt;h2gt;testlt;/h2gt; {products amp;amp; products.map((product) =gt; { return lt;ProductItem key={product.id} product={product} /gt;; })} lt;/RootContainergt; ); }; export default ProductsList;
Это функция GetProducts (), которая извлекает данные из другого порта.
const getProducts = async () =gt; { let API_URL = 'http://localhost:5000/api/Products'; const response: any = await fetch(API_URL); const data = await response.json(); return data; }; export default getProducts;
Комментарии:
1. Код, который вы написали здесь, выглядит довольно солидно. Не могли бы вы, возможно, дать немного больше контекста, включив GetProducts, Product и ProductItem? Я предполагаю, что продукты не проходят через реквизит, в результате чего он пуст или не определен, что по совпадению не вернет никаких элементов продукта.
2. Кроме того, создание песочницы из этого очень помогло бы
3. вы получаете продукты в качестве реквизита. Почему вы звоните
getProducts()
из эффекта использования в этом компоненте ? В любом случае вы можете console.log(продукты) непосредственно перед оператором return и посмотреть, что он содержит.
Ответ №1:
Я думаю, что проблема может заключаться в том, что вы извлекаете продукты, но на самом деле ничего с ними не делаете — поэтому проверка «продукты», которую вы выполняете перед повторением, вернет false.
Попробуйте использовать переменную состояния:
const ProductsList = () =gt; { const [products, setProducts] = useStatelt;product[]gt;(); useEffect(() =gt; { getProducts().then((result) =gt; setProducts(result); }, []); return ( lt;RootContainergt; lt;h2gt;testlt;/h2gt; {products amp;amp; products.map((product) =gt; { return lt;ProductItem key={product.id} product={product} /gt;; })} lt;/RootContainergt; ); };
Принцип здесь заключается в том, что при возврате метода GetProducts() он обновит переменную состояния списком продуктов. Это изменение состояния приведет к обновлению компонента и будет достигнута карта products.map.
Комментарии:
1. Д звучит многообещающе для вашего объяснения. Однако я получаю эту ошибку, когда передаю GetProducts(). Аргумент типа » Обещаниеlt;любойgt;» не может быть назначен параметру типа » SetStateActionlt;любойgt;lt;Продукт []gt;». Тип «Обещаниеlt;любойgt;» не может быть присвоен типу » (Предыдущее состояние: Продукт[]) =lt;любойgt;gt; Продукт []». Введите «Обещаниеlt;любоеgt;», чтобы подпись не соответствовала » (Предыдущее состояние: Продукт[]): Продукт []». ts(2345) продукты-список.tsx(20, 17): Вы забыли использовать «ожидание»?
2. Похоже, что ваш GetProducts() является асинхронным методом (вызов axios?). Не видя вашего кода, вы должны быть в состоянии сделать что-то вроде GetProducts().затем((результат) =gt; setProducts(результат));
3. Я обновил свой вопрос с помощью кода GetProducts ().
Ответ №2:
Вы получаете продукты на useEffect
крючке, но не сохраняете их как значение состояния. Попробуйте использовать useState
для достижения этой цели и попробуйте настроить логику рендеринга.
import {useState, useEffect} from 'react'; //... interface Props { products: Product[] | []; } const ProductsList = (props: Props) =gt; { const [products, setProducts] = useStatelt;Product[]gt;([]); useEffect(() =gt; { const _products = getProducts(); console.log('fetched data',_products); setProducts(_products); }, []); return ( lt;RootContainergt; lt;h2gt;testlt;/h2gt; {products amp;amp; products.map((product) =gt; { return lt;ProductItem key={product.id} product={product} /gt;; })} lt;/RootContainergt; ); }; export default ProductsList;
Если вы все еще ничего не видите, попробуйте изменить логику рендеринга следующим образом:
lt;RootContainergt; lt;h2gt;testlt;/h2gt; {products amp;amp; products.map((product) =gt; (lt;ProductItem key={product.id} product={product} /gt;) )} lt;/RootContainergt;
Поскольку вы используете TypeScript, условный рендеринг должен обрабатываться немного иначе, чем в JS. Так что в вашем чеке products amp;amp;
попробуйте это:
lt;RootContainergt; lt;h2gt;testlt;/h2gt; {products ? products.map((product) =gt; ( lt;ProductItem key={product.id} product={product} /gt;) : null )} lt;/RootContainergt;
Теперь, в зависимости от реквизитов, которые вы определили для компонента RootContainer, передача значения null в качестве a child
может быть недопустима. Если это так, попробуйте изменить значение null
на lt;gt;lt;/gt;
, чтобы вместо этого передать фрагмент реакции
Комментарии:
1. Я получаю ошибку, когда передаю GetProducts(). {products amp;amp; products.карта((продукт) =gt; { возврат gt;lt;ключ продукта={product.id} продукт={продукт} /gt;; })}
2. очень ценю ваши объяснения. С помощью обоих ответов в сочетании , наконец, это работает сейчас. .