How can I add Vanilla JS to my react app to create Image Modal pop-ups?

I am creating an image grid for a website Im making using React and I wanted to add a modal functionality to view each image as a modal pop-up. For this I need to use some Vanilla JS in combination with CSS and HTML. This is the js I want to use:

// Select the modal
var modal = document.getElementById('myModal');

// Get the image inside the modal
var img = document.getElementsByClassName('image');
var modalImg = document.getElementById("img01");
var captionText = document.getElementById("caption");
img.onclick = function(){
  modal.style.display = "block";
  modalImg.src = this.src;
  captionText.innerHTML = this.alt;
}

// Select the close button
var span = document.getElementsByClassName("close");

// Close Button 
span.onclick = function() { 
  modal.style.display = "none";
}

How can I integrate it with the rest of the app?

EDIT: This is the component I am working on:

import React from "react";
import "../stylesheets/Photos.scss";


const Photos = () => {
  return (
  <div className="photos_container">
      <h1 className="photos_title">PHOTO GALLERY</h1>
      <div className="row"> 
        <div className="column">
          <img className='image'src="../assets/photos_page/photo2.jpg"/>
          <img className='image' src="../assets/photos_page/photo3.jpg"/>
          
        </div>
        <div className="column">
          <img className='image' src="../assets/photos_page/photo4.jpg"/>
          <img className='image' src="../assets/photos_page/photo5.jpg"/>
          <img className='image' src="../assets/photos_page/photo6.jpg"/>
        </div> 
        <div className="column">
          <img className='image' src="../assets/photos_page/photo7.jpg"/>
          <img className='image' src="../assets/photos_page/photo8.png"/>
          <img className='image' src="../assets/photos_page/photo9.jpg"/>
        </div>
        <div className="column">
          <img className='image' src="../assets/photos_page/photo10.png"/>
          <img className='image' src="../assets/photos_page/photo11.jpg"/>
        </div>
      </div>
      {/* modal */}
      <div id='mymodal' className='modal'>
        <span className='close'>&times;</span>

        <img className='modal-content' id="img01"/>

        <div id='caption'></div>
      </div>
  </div>
  );
};

export default Photos;

Upvotes: 0

Views: 410

Answers (2)

jschuss
jschuss

Reputation: 655

Someone beat me to it, but I will still leave my version of the answer here in case you find it helpful. I would not select document elements in the mentioned way, because there is simpler and more declarative way. What you want to do is change this component into a stateful one, which contains a state property like "showmodal". When it is true, the modal should be shown. Then you can toggle the state and set the image which was clicked on by using this.setState({ showmodal: true, slectedImage: yourImage }) in your onClick function. A simple absolutely positioned container should do the trick for the modal container.

Here is an example of what such a component would look like.

  const images = [
  {
    uri:
      "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTm3CuNzOrmWhos3MXI0v_KkyO_xrZ5Y8hFxSYGj_6OtUygZUUX"

  },
  {
    uri:
      "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQR_Fg_lMrPjMa1duHXnvFnZOtsn883LGLD7c2-CwKdfFXAoveQnQ"
  }
];

class App extends React.Component {

  state = {
    showmodal: false,
    selectedImage: undefined
  };

  render() {
    // 
    return (
      <div style={{ height: "100vh"}}>
        {images.map(i => (
          <img
            key={i.uri}
            src={i.uri}
            style={{ margin: 5 }}
            onClick={() => this.setState({ showmodal: true, selectedImage: i })}
          />
        ))}
      {this.state.showmodal &&   
        <div
          onClick={() => this.setState({ showmodal: false })}
          style={{
            display: 'flex',
            position: "absolute",
            top: 0,
            bottom: 0,
            left: 0,
            right: 0,
            backgroundColor: "rgba(0,0,0,0.5)",
            justifyContent: 'center', alignItems: 'center'
          }}
        >
          <div style={{ height: 300, width: 500, backgroundColor: '#fff' }}>
            <img src={this.state.selectedImage.uri} style={{ flex: 1}} />
            <h3>Place any content here</h3>
          </div>
        </div>}
      </div>
    );
  }
}

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

I did not refactor out the styles so you can see what each div is doing as a super basic example which you can check out in codepen. Also, I agree with viz above in trying to refactor you columns so that you can render them the exact same way, and reduce duplication.

Hope it helps!

Upvotes: 1

viz
viz

Reputation: 1277

Everything in react is javascript, so

<div style={{display: this.state.showModal ? 'block' : 'none' }}>
  <span onClick={() => {this.state.showModal = false;}}>&times;</span>
  <img src={this.state.currentImage}/>
  <div>{this.state.currentCaption}</div>
</div>

and then set respective currentImage and currentCaption with setState upon the image click.

You should also consider programmatically composing the column & images' jsx so that it can be concise.

Upvotes: 0

Related Questions