Реагировать с помощью перехватов: как правильно обновлять состояние после события щелчка?

#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)}
        />