简体   繁体   中英

React with Hooks: how to correctly update state after a click event?

In my JSX, I'm, mapping through an array of objects (imported from a local JS file) to display a set of icons with a key, id and alt tag.

I use hooks to set a state to an empty string. I want to use an onClick event (passed to the HeroIcons component) to replace this state with the id of the clicked icon (that id is a string). Here's the code:

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;

Inside the heroIcons component:

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;

When clicking on an icon (created by the map function), the id isn't logged to the console. However, when I furiously click it many times, sometimes an id DOES get logged. This gives me a hint that this click event could be causing the map function to re-run and prevent the normal console log在此处输入图像描述

How could I fix this this issue?

First you have to use e.currentTarget.id instead of e.target.id so you get the id of current image.

  const setCurrentHero = e => {
    currentHero(e.currentTarget.id);
    console.log(hero);
  };

Second useState Hook needs you to handle the callback to use log the value of the current state, while it doesn't accept the callback like setState . You can use useEffect but It would better if you use the value of e.currentTarget.id ;

This is because you hero is not updated at the time of console so you need to use useEffect hook when that value is updated

 const setCurrentHero = e => { currentHero(e.target.id); console.log(hero); }; useEffect(() => { console.log('Hero', hero); }, [hero]);

why not just set the value in the render:

<HeroIcons
          key={id}
          id={id}
          src={src}
          altTag={altTag}
          setCurrentHero={setCurrentHero(id)}
        />

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM