Dynamic components: Calling element by ref

2019-06-01 18:30发布

问题:

One part of my application is an image gallery. When the user clicks on an image, I want to put an opaque layer over the image to visualize that it is selected.

When I display the layer, and I click on the image to deselect it, naturally I'm actually clicking on the layer. Here's the relevant ReactJS code to show what I mean:

{images.map((i, idx) => ( 
    <div key={"cont"+idx} className="container">
        <img src={i.images} ref={"img"+idx} />
        <div onClick={this.handleIconDeselect} id={"div_"+idx}></div>
    </div>  
    )
)}

I tried to give the img a unique ref (as shown above), but I'm having trouble selecting the correct img.

This is how I try to select the correct image:

handleIconDeselect = (event) => {
  var imgref = "icon"+event.target.id.split("_").pop();
  this.refs.imgref.click();
}

However, I get the following error message:

TypeError: Cannot read property 'click' of undefined

How can I select the correct image while using unique refs?

Alternatively, if the way I'm trying to achieve this is bad practice (I know you should only use refs when absolutely necessary), what is a better way to do it?

回答1:

Try use state as here: https://codesandbox.io/s/m4276x643y Maybe that is not the best way but it give you an rough idea.

import React, { Component } from "react";
import { render } from "react-dom";
import Hello from "./Hello";

const coverStyle = {
  position: "fixed",
  top: 0,
  left: 0,
  zIndex: -1,
  opacity: 0,
  width: "100%",
  height: "100%",
  background: "#000"
};

const coverStyleShow = {
  ...coverStyle,
  zIndex: 1,
  opacity: 1
};

const imgShow = {
  zIndex: 10,
  position: "relative"
};

const images = [
  "https://dummyimage.com/100.png/f10/fff",
  "https://dummyimage.com/100.png/f20/fff",
  "https://dummyimage.com/100.png/f30/fff",
  "https://dummyimage.com/100.png/f40/fff",
  "https://dummyimage.com/100.png/f50/fff",
  "https://dummyimage.com/100.png/f60/fff",
  "https://dummyimage.com/100.png/f70/fff"
];

class App extends Component {
  constructor(props) {
    super(props);

    this.state = {
      cover: coverStyle,
      img: imgShow,
      imgId: null,
      imgShow: false
    };
  }
  handleImageClick = (target, idx) => {
    // you can do something with this "target"...

    this.setState({
      cover: coverStyle,
      coverShow: coverStyleShow,
      imgId: idx,
      imgShow: !this.state.imgShow
    });
  };
  render() {
    return (
      <div>
        <Hello name="CodeSandbox" />
        <h2>Start editing to see some magic happen {"\u2728"}</h2>
        <div>
          {images.map((img, idx) => (
            <img
              key={img}
              src={img}
              style={idx === this.state.imgId ? this.state.img : null}
              onClick={event => this.handleImageClick(event.target, idx)}
              alt="dummy img"
            />
          ))}
        </div>
        <span
          style={this.state.imgShow ? this.state.coverShow : this.state.cover}
        />
      </div>
    );
  }
}

render(<App />, document.getElementById("root"));