В целом ход мыслей правильный. Но как именно тебе это реализовать, придется думать самому, потому что у тебя там фаербейз и прочие частные тонкости. И именно поэтому я и говорил изучать мой движок, потому что там все это из коробки идет. Ну, может со временем ты это осознаешь.
Понятно значит все-таки здесь нет затягивания покемона, я просто на гитхабе этот код смотрю, думал он рабочий. Весь мозг уже себе сломал не мог понять, как же он все-таки получает покемона. Значит все-таки я был частично прав, что должно быть еще получение даных для отоброжения покемона (про константу я понял). Правильно понимаю, что тогда нужно примерно реализовать такую же логику, как у нас в компоненте PokedexPage:

Сначала запускаем получение данных из самописного хука useData, который отвечает за получение данных.
const { data, isLoading, isError } = useData<IPokemons>('getPokemons', query, [debouncedValue]);
Потом скорей всего нужно объявить пустой useState и потом через useEffect туда положить покемона, только не совсем понимаю, как это все реализовать. Тут еще нужно в useEffect скорей всего сначала получить id из урла, а потом уже по этому id добовлять покемона в useState. Правильный вообще ход мыслей или вообще не туда?
>> Я правильно понимаю, что в props у нас попадает только id назначенный константой через деструктуризацию. А mockPockemon и stats мы создаем только для того, чтобы использовать в самом компоненте или все-таки они тоже каким-то образом появляются в пропсах?

Олег, не все переменные, что ты видишь внутри компонента, приходят через пропсы. Это могут быть просто другие переменные и константы из более высокой области видимости. В твоем случае mockPockemon - это просто константа, объявленная выше.
const mockPockemon: any = { abilities: ['blaze', 'solar-power'], exp: 240, height: 17, id: 6, img: 'https://raw.githubusercontent.com/PokeAPI/sprites/master/sprites/pokemon/other/official-artwork/6.png', is_default: true, name: 'charizard', order: 7, stats: { hp: 78, attack: 84, defense: 78, specialAttack: 109, specialDefense: 85, speed: 100 }, types: ['fire', 'flying'], weight: 905, };
В IDE ты можешь курсор поставить на нужную переменную и нажать F12, чтобы IDE тебе показала откуда берется эта переменная.

В этом, скорее всего, и кроется ответ на все твои здесь вопросы. Условно, когда ты переходишь на страницу покемона (имею ввиду компонент Pokemon), то у тебя на вход через пропсы заходит только id, а данные покемона берутся из вот этой единой константы mockPockemon (для всех покемонов). В таком случае, судя по всему, у тебя все карточки отображаются одинаково. А чтобы такого не было, тебе надо в компоненте запилить еще получение данных покемона. То есть на вход у тебя есть id, надо затянуть из источника данные конкрертно этого покемона.

Вообщем преамбула следующая, есть страница с каталогом карточек. Нужно на этой страницы по клику на карточку открыть эту карточку на другой странице.

Вот есть уже готовый код, но я не могу понять, как он работает. Примерно такую же задачу делал, но через Context API, но оказывается можно сделать по другому.

Сама страница, которая отвечает за вывод карточки:

import React from 'react'; import style from './Pokemon.module.scss'; import Layout from '../../components/Layout'; import Heading, { HeadingType } from '../../components/Heading'; export interface PokemonProps { id: string | number; } const mockPockemon: any = { abilities: ['blaze', 'solar-power'], exp: 240, height: 17, id: 6, img: 'https://raw.githubusercontent.com/PokeAPI/sprites/master/sprites/pokemon/other/official-artwork/6.png', is_default: true, name: 'charizard', order: 7, stats: { hp: 78, attack: 84, defense: 78, specialAttack: 109, specialDefense: 85, speed: 100 }, types: ['fire', 'flying'], weight: 905, }; const Pokemon: React.FC<PokemonProps> = (props) => { const { id } = props; const { img, name, exp, abilities, stats, types } = mockPockemon; const { hp, attack, defense, specialAttack, specialDefense } = stats; return ( <div className={style.root}> <Layout className={style.contentWrap}> <div className={style.pictureWrap}> <img src={img} alt={name} /> </div> <p> {types.map((it: string) => ( <span>{it}</span> ))} </p> <div className={style.stats}> <div className={style.header}> <Heading type={HeadingType.h3} className={style.name}> {name} </Heading> <p className={style.generation}>Generation 1</p> <div className={style.id}>{id}</div> </div> <div className={style.row}> <p>Abilities</p> {abilities.join(' - ')} </div> <div className={style.row}> <p> Healthy Points <br /> <span>{hp}</span> </p> <p> Experience <br /> <span>{exp}</span> </p> </div> <div className={style.row}> <div> <p>{defense}</p> <p>Defence</p> </div> <div> <p>{attack}</p> <p>Attack</p> </div> <div> <p>{specialAttack}</p> <p>Sp Attack</p> </div> <div> <p>{specialDefense}</p> <p>Sp Defense</p> </div> </div> </div> </Layout> </div> ); }; export default Pokemon;
Здесь меня во-первых меня заинтересовал странный вариант объявления пропсов:
const Pokemon: React.FC<PokemonProps> = (props) => { const { id } = props; const { img, name, exp, abilities, stats, types } = mockPockemon; const { hp, attack, defense, specialAttack, specialDefense } = stats;
Я правильно понимаю, что в props у нас попадает только id назначенный константой через деструктуризацию. А mockPockemon и stats мы создаем только для того, чтобы использовать в самом компоненте или все-таки они тоже каким-то образом появляются в пропсах?



Компонент самой карточки, которая отображается на странице каталога карточек:

import React from 'react'; import cn from 'classnames'; import Heading, { HeadingType } from '../Heading'; import style from './PokemonCard.module.scss'; import { IPokemon } from '../../interface/pokemons'; interface IPokemonCard { pokemon: IPokemon; onCardClick: (arg: any) => void; } const PokemonCard: React.FC<IPokemonCard> = (props) => { const { pokemon, onCardClick } = props; const { name, stats, types, img } = pokemon; return ( <div className={style.root} onClick={onCardClick} onKeyPress={onCardClick} role="button" tabIndex={0}> <div className={style.infoWrap}> <Heading type={HeadingType.h4} className={style.titleName}> {name} </Heading> <div className={style.statWrap}> <div className={style.statItem}> <div className={style.statValue}>{stats.attack}</div> Attack </div> <div className={style.statItem}> <div className={style.statValue}>{stats.defense}</div> Defense </div> </div> <div className={style.labelWrap}> {types.map((it: string) => ( <span className={cn(style.label, style[it as keyof typeof style])}>{it}</span> ))} </div> </div> <div className={cn(style.pictureWrap, style[types[0] as keyof typeof style])}> <img src={img} alt={name} /> </div> </div> ); }; export default PokemonCard;
Вот здесь я так понимаю все что назначено через деструктуризацию попадает в пропсы, так как pokemon присваивается в props. Помимо этого мы еще добовляем событие onCardClick повешеное на style.root.



Страница где выводится каталог карточек:
import React, { useState } from 'react'; import { navigate } from 'hookrouter'; import Layout from '../../components/Layout'; import Heading, { HeadingType } from '../../components/Heading'; import PokemonCard from '../../components/PokemonCard'; import useDebounce from '../../hook/useDebounce'; import useData from '../../hook/getData'; import { IPokemons } from '../../interface/pokemons'; import { parsePokemons } from '../../adapters/pokemons'; import { LinkEnum } from '../../routes'; import style from './Pokedex.module.scss'; interface IQuery { name?: string; } const PokedexPage = () => { const [searchValue, setSearchValue] = useState<string>(''); const debouncedValue = useDebounce(searchValue, 500); const [query, setQuery] = useState<IQuery>({}); const { data, isLoading, isError } = useData<IPokemons>('getPokemons', query, [debouncedValue]); const parsedPokemons = data && parsePokemons(data.pokemons); const handleSearchChange = (evt: React.ChangeEvent<HTMLInputElement>) => { setSearchValue(evt.target.value); setQuery((state) => ({ ...state, name: evt.target.value, })); }; const handleCardClick = (id: number) => { navigate(LinkEnum.POKEMON.replace(':id', String(id))); }; if (isLoading) { return <div>Loading...</div>; } if (isError) { return <div>Error!</div>; } return ( <div className={style.root}> <Layout className={style.contentWrap}> <Heading type={HeadingType.h3} className={style.heading}> {data && data.total} <strong>Pokemons</strong> for you to choose your favorite </Heading> <input type="text" className={style.search} placeholder="Encuentra tu pokémon..." value={searchValue} onChange={handleSearchChange} /> filters <div className={style.pokemonList}> {parsedPokemons && parsedPokemons.map((it) => ( <PokemonCard key={it.id} pokemon={it} onCardClick={() => handleCardClick(it.id)} /> ))} </div> pagination </Layout> </div> ); }; export default PokedexPage;

Все что связано с поиском по карточкам меня не интересует. Меня интересует, как работает именно передача карточки на страницу Pokemon.

Я вижу, что мы мапой проходимся по parsedPokemons в котором у нас лежат данные и выводим их компонентом PokemonCard.

{parsedPokemons && parsedPokemons.map((it) => ( <PokemonCard key={it.id} pokemon={it} onCardClick={() => handleCardClick(it.id)} /> ))}
Так же мы из пропсов PokemonCard вызываем пропс onCardClick и через стрелочную функцию вызываем handleCardClick, который у нас объявлен в этом компоненте, который нас перекидывает на страницу Pokemon. Хорошо он нас перекинул - в хендлере вижу только формирование страницы host/pokemon/id и переброс на страницу, а как сам вывод карточки покемона осущевстляется на самой странице? По моей логике туда тоже должна прийти тогда дата из апишки из которой мы по id допустим делаем вывод, но я не вижу, чтобы туда дата приходила, кроме приходящего id больше ничего не вижу, может я чего-то не догоняю.

И поделись информацией, какие еще есть варианты, чтобы осуществить даную логику клик по карточке и вывод ее на другой странице.
Супер! Спасибо)
Я сам выпал как-то...
Проблема в кодировке файла .env, там русские буквы каракулями были

Надо запускать с параметром, указывающим адрес АПИ-сервера, например API_URL=http://localhost:2016 yarn dev
Дима, привет!

Сорри за долгий ответ, был не на связи. В подобных случаях не жди меня, сам себе задачи придумывай :)
Ну а вообще, можешь начинать делать страницу компании. Для начала хотя бы роутинг и получение данных реализуй, а окончательный вывод потом.

БД только с данными по России занимает 84GB
Николай, привет!
Код изучил - так-то все понятно. Понять понимаю, а сказать - не могу))
То есть повторить его логику) Надо двигать дальше. Как думаешь, куда двигать?