#reactjs #typescript #axios
#reactjs #машинописный текст #аксиос
Вопрос:
Я пытаюсь переместить свой запрос API в отдельную службу и столкнулся с этой проблемой.
Вот мой интерфейс
export interface IProduct {
id: any;
productName: string;
productDescription: string;
productImage: string;
productPrice: any;
categoryId: string;
category: any;
}
Вот компоненты для списка продуктов
import React, {useEffect, useState} from 'react';
import {IProduct} from "../models"
interface IProps {
products: IProduct[];
}
export const ProductsList: React.FC<IProps> = ({products}) => {
return (
<div className="App">
<ul className="posts">
{products.map((products) => (
<li key={products.id}>
<h3>{products.productName}</h3>
<p>{products.productDescription}</p>
<h2>{products.productPrice}</h2>
</li>
))}
</ul>
</div>
);
}
export default ProductsList;
Далее Api.tsx
, где я пытаюсь сделать запрос:
import axios, { CancelTokenSource } from "axios";
import {IProduct} from "../models"
import React from 'react';
export const fetchAllProducts = async (setData: IProduct[]): Promise<IProduct[]> => {
return axios.get<IProduct[]>("https://localhost:5001/api/ShowAllProducts")
.then(response => {return setData = response.data });
}
и, наконец, APP.tsx
import axios, { CancelTokenSource } from "axios";
import {IProduct} from "./models"
import {ProductsList} from "./components/ProductsList";
import React from 'react';
import {fetchAllProducts} from './services/api';
const defaultProps:IProduct[] = [];
function App() {
const [products, setProducts] = React.useState<IProduct[]>
(defaultProps)
const [loading, setLoading]: [boolean, (loading: boolean) => void] = React.useState<boolean>(true);
const [error, setError]: [string, (error: string) => void] = React.useState("");
return (
<div>
<ProductsList products= {fetchAllProducts(products)}/>
</div>
);
}
export default App;
Итак, у меня есть ошибка в app.tsx в return прямо перед символом «=» на продуктах.
В нем говорится:
Type 'Promise<IProduct[]>' is missing the following properties from type 'IProduct[]': length, pop, push, concat, and 28 more.ts(2740)
ProductsList.tsx(6, 5): The expected type comes from property 'products' which is declared here on type 'IntrinsicAttributes amp; IProps amp; { children?: ReactNode; }'
Комментарии:
1.
fetchAllProducts
возвращает `Обещание<IProduct[]>. You're trying to pass that as a prop, which expects an
IProduct[]`.
Ответ №1:
Мне кажется, что строка
.then(response => {return setData = response.data });
должно быть переписано как:
.then(response => Promise.resolve(response.data));
Это должно решить вашу проблему
Комментарии:
1. спасибо, я понял это, я думал, что второй аргумент в const[X, Y] — это просто var , но это функция, поэтому я изменил свои аргументы api, чтобы он мог принимать func .
Ответ №2:
Те свойства, которые в сообщении об ошибке указаны как отсутствующие, являются свойствами массива.
interface IProps {
products: IProduct[];
}
export const ProductsList: React.FC<IProps> = ({products}) => {
...
}
В приведенном выше коде вы указываете ProductsList
компоненту ожидать массив с именем products в качестве реквизита.
Но в APP.tsx в строке
<ProductsList products= {fetchAllProducts(products)}/>
вы отправляете fetchAllProducts(products)
в качестве products
реквизита. fetchAllProducts(products)
это функция, которая возвращает обещание, а не массив.
Чтобы исправить это, вы могли бы написать что-то вроде:
function App() {
const [products, setProducts] = React.useState<IProduct[]>
(defaultProps)
const [loading, setLoading]: [boolean, (loading: boolean) => void] = React.useState<boolean>(true);
const [error, setError]: [string, (error: string) => void] = React.useState("");
React.useEffect(async () => {
const allproducts = await fetchAllProducts();
setProducts(allproducts)
}, [])
return (
<div>
<ProductsList products={products}/>
</div>
);
}
Таким образом, вы извлекаете все продукты при App
монтировании компонента и передаете массив в качестве products
реквизита ProductsList
.
Комментарии:
1. спасибо, я понял это, я думал, что второй аргумент в const[X, Y] — это просто var , но это функция, поэтому я изменил свои аргументы api, чтобы он мог принимать func .
Ответ №3:
Спасибо всем вам, ребята, я понял это, кстати, ваши ответы помогли мне понять одну вещь. я думал, что
const [products, setProducts] = React.useState<IProduct[]>(defaultProps)
похоже на typesriptish {set; get;} из .net lol.
но теперь я знаю, что второй аргумент — это функция. поэтому я просто изменил аргумент в своем файле api.tsx, чтобы он теперь принимал функции.
таким образом, компонент и интерфейс остаются без изменений
вот мой api.tsx
export const fetchAllProducts = async (func: any): Promise<IProduct[]> => {
return axios.get<IProduct[]> ("https://localhost:5001/api/ShowAllProducts")
.then(response => {return func(response.data)});}
и вот APP.tsx
const defaultProps:IProduct[] = [];
function App() {
const [products, setProducts] = React.useState<IProduct[]>(defaultProps)
const [loading, setLoading]: [boolean, (loading: boolean) => void] =
React.useState<boolean>(true);
const [error, setError]: [string, (error: string) => void] =
React.useState("");
React.useEffect(() => {
async () => await fetchAllProducts(setProducts);
}, [])
return (
<div>
<ProductsList products={products}/>
</div>
);
}
export default App;