#javascript #reactjs #higher-order-functions #rerender
#javascript #reactjs #функции более высокого порядка #повторный запуск
Вопрос:
В моем JSX я сопоставляю массив объектов (импортированных из локального файла JS) для отображения набора значков с ключом, идентификатором и тегом alt.
Я использую перехваты для установки состояния в пустую строку. Я хочу использовать событие onClick (переданное компоненту HeroIcons), чтобы заменить это состояние идентификатором нажатой иконки (этот идентификатор представляет собой строку). Вот код:
import React, { useState } from "react";
import HeroImages from "../images/HeroImages";
import HeroIcons from "../components/HeroIcons";
import HeroShowcase from "../components/HeroShowcase";
const Heroes = () => {
const [hero, currentHero] = useState("");
const setCurrentHero = e => {
currentHero(e.target.id);
console.log(hero);
};
return (
<div className="row">
<div className="col-heroes">
<ul className="hero-list">
{/* map function below */}
{HeroImages.map(({ id, src, altTag }) => (
<HeroIcons
key={id}
id={id}
src={src}
altTag={altTag}
setCurrentHero={setCurrentHero}
/>
))}
</ul>
</div>
<div className="col-showcase">
<HeroShowcase />
</div>
</div>
);
};
export default Heroes;
Внутри компонента heroIcons:
import React from "react";
const HeroIcons = props => {
return (
<li key={props.id} id={props.id} onClick={props.setCurrentHero}>
<img src={props.src} alt={props.altTag} />
</li>
);
};
export default HeroIcons;
При нажатии на значок (созданный функцией map) идентификатор не регистрируется в консоли. Однако, когда я яростно нажимаю на него много раз, иногда идентификатор регистрируется. Это дает мне подсказку, что это событие щелчка может привести к повторному запуску функции map и предотвращению обычного журнала консоли
Как я могу исправить эту проблему?
Ответ №1:
Сначала вы должны использовать e.currentTarget.id
вместо e.target.id
, чтобы получить id
текущее изображение.
const setCurrentHero = e => {
currentHero(e.currentTarget.id);
console.log(hero);
};
Второй useState
перехват требует, чтобы вы обрабатывали обратный вызов, чтобы использовать log
значение текущего состояния, в то время как он не принимает callback
подобное setState
.
Вы можете использовать useEffect
, но было бы лучше, если бы вы использовали значение e.currentTarget.id
;
Комментарии:
1. спасибо, используя e.currentTarget.id помогли решить эту проблему. Я также использую ваше предложение и предложение Zohaib Ijaz о useEffect. Сейчас я получаю идентификатор героя, на которого нажали, но я также изучаю, как предотвратить запуск этого после первой загрузки страницы
2. Если я вас правильно понимаю, вы также можете использовать ‘useEffect’ и передать ему пустой массив для достижения ‘componentDidMount’.
3. итак, я применил ваши решения и @ZohaibIjaz вместе взятые. Теперь это мой код
const [hero, currentHero] = useState(""); const setCurrentHero = e => { currentHero(e.currentTarget.id); }; useEffect(() => { console.log("Current hero is:", hero); }, [hero]);
В журнале консоли после первой загрузки страницы включена строка «текущий герой:» (без идентификатора). Интересно, смогу ли я зарегистрировать это только после запуска события щелчка4. Если я вас понимаю, вы можете написать это так
if (hero) console.log("Current hero is:", hero);
5. Спасибо, «оператор if» помог мне теперь достичь желаемого результата 🙂
Ответ №2:
Это потому, что вы hero
не обновляетесь во время консоли, поэтому вам нужно использовать useEffect
перехват при обновлении этого значения
const setCurrentHero = e => {
currentHero(e.target.id);
console.log(hero);
};
useEffect(() => {
console.log('Hero', hero);
}, [hero]);
Ответ №3:
почему бы просто не установить значение в рендеринге:
<HeroIcons
key={id}
id={id}
src={src}
altTag={altTag}
setCurrentHero={setCurrentHero(id)}
/>