#javascript #arrays #reactjs #typescript
Вопрос:
Кажется, я не могу разобраться в циклических массивах/объектах. Я довольно часто застреваю в них. Как здесь, например, я не могу повторить данные из api, я получаю trending is not a function
ошибку. Может ли кто-нибудь помочь мне исправить это и дать мне какое-нибудь хорошее направление, чтобы лучше зацикливаться
Интерфейс
export interface Item {
id: string;
name: string;
symbol: string;
market_cap_rank: number;
thumb: string;
large: string;
score: number;
}
export interface Coin {
item: Item;
}
export interface ResponseObject{
coins: Coin[];
}
Код
import React, { useEffect, useState} from 'react'
import axios from 'axios'
import { ResponseObject } from '../interfaces';
const TRENDING = 'https://api.coingecko.com/api/v3/search/trending'
const Home:React.FC= () => {
const [trending, setTrending ] = useState<ResponseObject[]>([])
useEffect(()=>{
axios
.get<ResponseObject[]>(TRENDING)
.then((response) =>
{setTrending(response.data);
console.log(response) })
.catch(err =>
{ console.log(err); })
},[])
return (
<div>
{trending.map(trend =>
(<div key={trend.item.id}>{trend.item.name}</div>))}
</div>
)
}
export default Home
API
{
"coins":[
{
"item":{
"id":"superfarm",
"name":"SuperFarm",
"symbol":"SUPER",
"market_cap_rank":235,
"thumb":"https://assets.coingecko.com/coins/images/14040/thumb/6YPdWn6.png?1613975899",
"large":"https://assets.coingecko.com/coins/images/14040/large/6YPdWn6.png?1613975899",
"score":0
}
},
{...}
],
"exchanges":[]
}
Комментарии:
1. разве вы не должны переходить
response.data.coins
в setState?
Ответ №1:
Я предполагаю, что вы, вероятно, установили объект в качестве трендового, а не массива. response.data
должен возвращать объект, который будет похож на ваш API.
// response.data should return this object.
{
"coins":[
{
"item":{
"id":"superfarm",
"name":"SuperFarm",
"symbol":"SUPER",
"market_cap_rank":235,
"thumb":"https://assets.coingecko.com/coins/images/14040/thumb/6YPdWn6.png?1613975899",
"large":"https://assets.coingecko.com/coins/images/14040/large/6YPdWn6.png?1613975899",
"score":0
}
},
{...}
],
"exchanges":[]
}
Вы должны установить response.data.coins
в качестве тенденции, которая вернет массив.
[
{
"item":{
"id":"superfarm",
"name":"SuperFarm",
"symbol":"SUPER",
"market_cap_rank":235,
"thumb":"https://assets.coingecko.com/coins/images/14040/thumb/6YPdWn6.png?1613975899",
"large":"https://assets.coingecko.com/coins/images/14040/large/6YPdWn6.png?1613975899",
"score":0
}
},
{...}
]
Комментарии:
1. Я получаю свойство «монеты», которого не существует в объекте типа ответа
2. Не могли бы вы, пожалуйста
console.log(response)
, поделиться здесь?3. держи, извини, что меня здесь не было. imgur.com/POxMzvY
4. @Текила, я сделал для тебя песочницу: codesandbox.io/s/api-coingecko-1qnu9
5.
response.data
имеет типResponseObject
(как вы указали вaxios.get
).response.data.coins
isCoins[]
(массив монет). И я написалsetTrending(response.data.coins);
в API success. Это означает, что я устанавливаюresponse.data.coins
(типаCoin[]
) в состояние, т. Е.trending
. Итак, мне нужно сказатьuseState
, что я буду устанавливатьCoin[]
тип данных вместе с вами. Вот почему я написалuseState<Coin[]>([]);
.
Ответ №2:
Проблема не имеет ничего общего с цикличностью.
Вы вызываете setTrending
что-то, что не является массивом. вот почему вы получаете trending.map is not a function
.
Ваш API напрямую возвращает не массив, а объект с двумя ключами, каждый из которых содержит массив.
В вашем случае вы должны позвонить setTrending(response.data.coins)
.
ИЗМЕНИТЬ: вы также должны исправить свое ResponseObject
использование:
const [trending, setTrending ] = useState<Coin[]>([]);
useEffect(()=> {
axios
.get<ResponseObject>(TRENDING)
.then((response) => {
setTrending(response.data.coins);
})
.catch(err => console.log(err));
},[]);
Комментарии:
1. Я получаю свойство «монеты», которого не существует в объекте типа ответа