简体   繁体   中英

is it possible to select child element when you click on parent element in react, and the add a class to the parent element after an event

I am making a game with react, it's a memory game where you match images.so what I want to archive is, when I click on the div it selects the child of the div(the image) and then add class to the parent and then add class to the child itself. Based on the game logic I have to select the the child element first then if pass some conditions I then add a class to it and it's parent element. look at the code I currently have but it's not working, please help me out. `

let currentElement;
const imageclick=(e)=>{
    //select current image
    currentElement=e.target.firstElementChild;
    // some game  logic the add class to child and parent
    //add class to parent
    currentElement.closest("div").classList.add("show");
    //add class to child
    currentElement.classList.remove("hidden")
}

const app=()=>{
    return(
        <div className="imgDiv transition" key={i} onClick={imageclick}>
        <img src={img} alt="" className="tileImage hidden" />
        </div>
    )
}

`

There are multiple approaches.

One way is to store your images in an array of objects. This array is used to render all of your images. You could even shuffle the array to make the order random.

Inside your component you have a state. This state tracks the index of the currently selected image of the array. The initial state can be null to indicate that there is no current selected image.

While looping over your images, check for each image if the selectedImageIndex is equal to the index of the current image. If so, pass some extra classes.

(You don't need to toggle hidden class on the image. Use the show class on the div to either show or hide the child image).

Pass the index of the current image to the imageClick function in the onClick handler of the div . Whenever we click an image, we want to set the index of the image as our selectedImageIndex .

The component will now rerender and add the class to the clicked div .


Edit

I've modified the answer according to your comment. This example allows for 2 indexes to be stored into the state that tracks the selected images.

Whenever you click the same, the image is deselected. Whenever you click another image it will add its index to the state.

In the useEffect hook you can asses if the images corresponding to the indexes have a similar src or other property that matches.

(I would recommend creating a more robust system in which YOU say which images are the same instead of depending on the URL to be the same. Eg two images can be the same while having different URL's)

const images = [
  {
    id: 'A',
    src: 'your-image.jpg',
    alt: 'Something about your image'
  },
  {
    id: 'B'
    src: 'your-other-image.jpg',
    alt: 'Something about your image'
  },
  {
    id: 'A' // The match to the other A
    src: 'the-other-image-that-matches-the-first.jpg',
    alt: 'Something about your image'
  }
];

const App = () => {
  const [selectedImageIndexes, setSelectedImageIndexes] = useState([null, null]);

  const imageClick = index => {
    setSelectedImageIndex(currentIndexes => {
      // If the same index is clicked, deselect all.
      if (currentIndexes.includes(index)) {
        return [null, null];
      }

      // If no indexes have been set.
      if (currentIndexes.every(index => index === null)) {
        return [index, null];
      }

      // Set the second clicked image.
      return [currentIndexes[0], index];
    });
  };

  useEffect(() => {
    // If both indexes are set.
    if (selectedImageIndexes.every(index => index !== null) {
      
      /**
       * With the indexes in the selectedImageIndexes state,
       * check if the images corresponding to the indexes are matches.
       */
      if (selectedImageIndexes[0].id === selectedImageIndexes[1].id) {
        // Match!
      }
    }
  }, [selectedImageIndexes]);

  return (
    <div className="images">
      {images.map((image, index) => {
        const className = selectedImageIndex.includes(index) ? 'show' : '';

        return (
          <div className="imgDiv transition" key={`img-div-${index}`} onClick={() => imageClick(index)}>
            <img src={image.src} className="tileImage" alt={image.alt} />
          </div>
        );
      })}
    </div>
  )
};

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