Почему в React (в методе map) не получается использовать item в цепочке вызова свойств объекта?
Мне нужно было отрендерить большое количество одинаковых элементов (карточек), которые должны были отличаться картинкой и названием. Вот компонент для создания экземпляра карточки:
function PokemonCard(props) {
return (
<figure className="PokemonCard">
<img
src={`https://raw.githubusercontent.com/PokeAPI/sprites/master/sprites/pokemon/other/official-artwork/${props.pokemonKey}.png`}
alt={props.pokemonName}
/>
<figcaption>
{props.pokemonName}
</figcaption>
</figure>
)
};
Вот как я рендерил их в App компоненте:
function App() {
const arr = Array.from(Array(50).keys());
const pokemons = useSelector((state) => state.pokemonsList.pokemons);
const dispatch = useDispatch();
useEffect(() => {
dispatch(fetchPokemonsList());
}, [dispatch]);
return (
<div className="App">
<div
className="cardsWrapper"
>
{pokemons.results
&& arr.map((item, index) => {
return (
<PokemonCard
key={item}
pokemonKey={++item}
pokemonName={pokemons.results[item].name}
/>
)
})}
</div>
</div>
);
}
Здесь важно const arr = Array.from(Array(50).keys());. Я создал массив заполненный числами от 0 до 49, который я потом использую, чтобы запустить map (в случае успешного запроса данных) и вернуть нужное количество карточек с нужными мне свойствами.
После успешного запроса, в store сидят вот такие данные:
pokemons: {
count: 1050,
next: "https://pokeapi.co/api/v2/pokemon?offset=50&limit=50",
previous: null,
results: [
{
"name": "bulbasaur",
"url": "https://pokeapi.co/api/v2/pokemon/1/"
},
{
"name": "ivysaur",
"url": "https://pokeapi.co/api/v2/pokemon/2/"
},
...
В этом виде, из-за строчки pokemonName={pokemons.results[item].name} react выдаёт ошибку "TypeError: pokemons.results[item] is undefined". Но если объявить новую переменную и присвоить ей item, то всё будет работать, т.е.:
{pokemons.results
&& arr.map((item, index) => {
let sameItem = item; //добавляем эту строчку
return (
<PokemonCard
key={item}
pokemonKey={++item}
pokemonName={pokemons.results[sameItem].name} //меняем item на sameItem
/>
)
})}
Если использовать index вместо item, тоже будет всё работать.
{pokemons.results
&& arr.map((item, index) => {
return (
<PokemonCard
key={item}
pokemonKey={++item}
pokemonName={pokemons.results[index].name} //Ставим index вместо item
/>
)
})}
Вопрос.
Почему переменная item, из которой в возвращаемый экземпляр карточки попадает обычное число (так же, как если бы мы использовали индекс), выдаёт undefined в цепочке вызова свойств объекта: pokemons.results[item].name? Хотя, если убрать name, то react вернёт такую ошибку: "Error: Objects are not valid as a React child (found: object with keys {name, url})." То есть, мы получаем нужный объект из масива, но не можем обратиться к его свойству дальше по цепочке. Почему здесь именно item в map создаёт такую проблему?
Следует добавить, что цепочка работает, если не писать её именно в свойстве экземпляра компонента (т.е. в pokemonName). Вот так тоже всё работает:
{pokemons.results
&& arr.map((item, inbdex) => {
let name = pokemons.results[item].name; //переносим цепочку в переменную
return (
<PokemonCard
key={item}
pokemonKey={++item}
pokemonName={name} //добавляем её сюда
/>
)
})}