.board_table
)return
- она ничего и не возвращает. React в этом плане ничего не меняет.recipes.map((recipe) => {
<h2>{recipe.recipe.calories}</h2>; //не отображается
})
->recipes.map((recipe) => {
return (<h2>{recipe.recipe.calories}</h2>);
})
или recipes.map((recipe) => (
<h2>{recipe.recipe.calories}</h2>;
))
interface API {}
class Animal implements API {}
class Human implements API {}
const getInstance = (key: keyof typeof dict): API => {};
interface ClassDictionary {
animal: typeof Animal,
human: typeof Human
}
const dict = {
animal: Animal,
human: Human
} as ClassDictionary;
// ...
class Car implements API {}
dict.car = Car;
interface ClassDictionary {
car: typeof Car,
}
И кроме того, смущает, что по факту тип моего инстанса всегда будет Animal | Human.
if (instance instanceof Animal)
, внутри он уже чётко будет Animal
, очевидно. А проверку тебе в любом случае придётся делать, так что не вижу в чём конкретно проблема? Ты хочешь вызывать произвольные методы в произвольный момент времени без проверки? Или что? export interface Hit {
recipe: Recipe[];
}
-> export interface Hit {
recipe: Recipe;
}
Recipe
и компонент Recipe
, они конфликтуют скорее всего. Также возможно сам компонент Recipe
не типизирован, т.е. ts не знает какие пропсы он принимает, а какие нет.<список переданных пропсов>
нельзя назначить в <стандартные атрибуты для React-комонента>
, пропс title
отсутствует в <стандартные атрибуты для React-комонента>
". axios
(сервер) тебе вернёт Welcome
, а не Welcome['hits']
, потому так и пиши: const response = await axios.get<Welcome>(
`https://api.edamam.com/search?q=${query}&app_id=${ID}&app_key=${KEY}`
);
А вот в setRecipes
ты уже хочешь положить именно Welcome['hits']
а не весь Welcome
, потому тоже так и пиши React.useState<Welcome["hits"]>([])
// ...
setRecipes(response.data.hits)
axios
просто устанавливает какой тип будет у response.data
. Property 'hits' does not exist on type 'Ingredient[]'
только если ты сам напишешь вот так await axios.get<Ingredient[]>...
. Т.е. ты прямым текстом говоришь typescript'у, что в ответе сервера ждёшь МАССИВ Ingredient[]
, а не объект, имеющий поле hits
, а потом удивляешься, что он тебе об этом прямо говорит.React
.responce.data
у тебя корневой объект ответа, а не массив. Не массив. Не. Массив. setRecipes
массив hits
, то и клади туда, блин, массив hits
: setRecipes(response.data.hits)
.setRecipes
не меняет магически на лету recipes
, он обновляет state
(состояние) компонента. Поэтому функция и называется useState
, а не как-то ещё.recipes
будет тем которое ты установил.recipes
пустым массивом, создаётся функция fetchApi
в которую замыкается пустой recipes
.useEffect
и вызывает функцию fetchApi
.setRecipes
, выводится console.log
с запомненным пустым recipes
.setRecipes
инициирует повторную отрисовка компонента(повторный вызов функции-компонента), при которой в recipes
уже лежит то, что туда положили на предыдущем шаге. После отрисовки useEffect
не срабатывает, т.к. query
не менялся. setRecipes
всё ещё кладёшь response.data
, в response.data
у тебя весь ответ от сервера. Это не массив, а объект, вот этот: map
'ом пройтись по объекту.recipes
- может быть undefined
, потому что тут const[recipes, setRecipes] = React.useState<Welcome>();
не задал значение по умолчанию: useState()
условно то же самое, что useState(undefined)
, а значит у тебя в recipes
лежит undefined
до тех пока не придёт ответ от сервера. А ответ от сервера может прийти через сто лет, к тому времени компонент уже нарисовался и recipes.map
был вызван, т.е. undefined.map
, а это ошибка и падение скрипта. TS не даёт тебе этого сделать. Ты должен либо добавить проверку, что recipes
существует, либо задать значение по умолчанию, например пустой массив.populate
умеет это делать - тыкни в него и посмотри как там сделано. Возможно там уже есть готовый дженерик для этого, который достаточно просто импортировать, ну а если нет - не вижу сложности выдрать тип и написать что надо по образу и подобию.