Реакция: Почему на .map массив не показывает список элементов?

#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. очень ценю ваши объяснения. С помощью обоих ответов в сочетании , наконец, это работает сейчас. .