0

I have a webpage which I am building using React JS. The webpage displays a list of images in the map function within render. When I click on the image, as would be expected from my code, a border appears around every image in the map function. However, I only want a border to appear for the image that has been clicked. Any idea how I can modify my code to do that? Thanks.

import React from 'react';
import { Container, Button} from 'reactstrap';
import './scrapeInstagram.css';

const CSSVariables = {
  border : {
      border : '2px solid green'
  },
  noBorder : {
      border : '2px solid transparent'
  },
};

export default class ScrapeInstagram extends React.Component { 
    constructor(props) {
        super(props);
        this.state = {
            showBorder : false
        };
        this.searchTerms = props.location.params["searchTerms"];
        this.searchResults = props.location.params["searchResults"].filePaths;
        this.imageClick = this.imageClick.bind(this);
    }

    imageClick(image_src) {
        this.setState(state => ({ showBorder: !state.showBorder }))
    }


    render() {
        return (
            <Container>
            <center>
            <h1> IMAGES!!! </h1>
            <div className="box">
            {this.searchResults.map((photo) => {
                return <div className="dataSetBox" key={photo.toString()}><img id={this.state.ID} src={photo} onClick={() => { this.imageClick(photo.toString()) }} style={this.state.showBorder ? CSSVariables.border : CSSVariables.noBorder} alt="Image" height="350" width="450" margin="100px" /></div>;
            })}
            </div>
            </center>
            </Container>  
        );
  }
}
3
  • You don't need to store anything in the state just do onClick((event) => {event.target.style = CSSVariables.border}) Commented Mar 7, 2018 at 21:10
  • @EgorEgorov thanks for the response - unfortunately, I am unable to get that to work. I get no errors, but the border does not show up Commented Mar 7, 2018 at 21:33
  • take a look at this: codesandbox.io/embed/7mnomqw65q Commented Mar 7, 2018 at 22:03

2 Answers 2

1

You can use a CSS class to the same

class Images extends React.Component{
    state = {
        selected: []
    }

    selectImage(id){
        var selected = this.state.selected;
        if(selected.indexOf(id) !== -1) selected.push(id);
        this.setState({selected: selected});
    }

    render(){
        return (
           <div className="images">
               <ul>
                   {images.map(img => {
                       return <li><img id={img.id} src={img.src} onClick={this.selectImage.bind(this, img.id)} className={(this.state.selected.indexOf(img.id) !== -1)?"selected":"not-selected"} alt="Image" height="350" width="450" margin="100px" /></li>
                   })}
               </ul>
           </div>
        )
    }
}

And in your CSS

.selected{
    border: 2px solid green;
}

.not-selected{
    border: 2px solid transparent;
}

Hope this help, let me know if any confusion.

Sign up to request clarification or add additional context in comments.

Comments

0

Your state only stores one boolean value for all the images. It is normal that when this boolean is true, all the images get the border. Instead of a boolean, you should store for example the "src" of the last clicked photo. Then, for each img, you could do something like :

<img
    src={photo}
    onClick={() => { this.imageClick(photo) }}
    style={this.state.lastClicked === photo ? CSSVariables.border : CSSVariables.noBorder}
    alt="Image"
    height="350" width="450" margin="100px" />

2 Comments

Your answer makes sense! Do you have any idea how I could toggle on/off multiple images' borders? I tried creating an array and adding image ID's to the array if selected and removing if reselected. Then for style, it checks if the image ID is in the array before returning a border. However, since render happens in the beginning, clicking the images has no effect on the border
You can store an array of IDs in your component's state. The imageClick (that receive the clicked image's id) could make something like : setState((prevState) => { if(selectedIDs.includes(id)) { return { selectedIDs: prevState.selectedIDs.filter((i) => i !== id) } } else { return { selectedIDs: [ ...prevState.selectedIDs, id ] } } }). Do not forget that each call to setState triggers a re-render so the UI will be updated to reflect the change.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.