1

this code here works but I don't know how to just click one of my component in >the array with this code I can change the color. but I want to know how can I not change the color when I already change it in one >component thanks for the future answer

import React, { Component } from 'react';


export default class Seats extends Component {
    constructor() {
        super()
        this.state = {
            status: false,
        };
    }
    
    changeColor(event) {
        if (this.state.status === false) {
            event.currentTarget.style.backgroundColor = '#D70202';
            this.state.status = true;
        }else {
            this.state.status = false;
             event.currentTarget.style.backgroundColor = '#0CB607';
        }        
    }
    
     render() {
        let array = [];
        for (var i = 0; i < 5; i++) {
            array[i] = i;
        }
        
        const list = array.map((d, index) => <div className="seat"      onClick={this.changeColor.bind(this)} key={index}></div>);
        return (
            <div>
                {list}
            </div>
        );
    }
}
    
    
.seat {
    background-color: #0CB607; 
    border: 1px solid black;
    height: 90px;
    width: 90px;
}

2
  • Don't quite understand your question. Are you saying that once one of the array elements has been clicked, you don't want any others to be clicked and change colour? Or if another is clicked, you want the current selected one to return to its regular colour and change the colour of the newly clicked one? Commented Sep 12, 2017 at 1:02
  • I don't want any others to be clicked until I clicked again the one I did Commented Sep 12, 2017 at 2:15

1 Answer 1

1

There are two problems here, which need to be resolved separately:

  1. Instead of using this.state.status = true|false you should use this.setState({ status: true|false }). This forces a re-render.

  2. In your current approach, you are managing your state via just manipulating the DOM directly, setting the style.backgroundColor. This will get blown away the next time your component renders.

To address the second issue, I suggest storing the array of items you are manipulating as state at the component level. As an example:

JS:

export default class Seats extends React.Component {
  constructor() {
    super()

    const seats = [...Array(5)].map(() => ({ status: false }))
    this.state = { seats }
  }

  handleSeatClick(index) {
    const seats = this.state.seats
    const seat = seats[index]
    seat.status = !seat.status

    seats[index] = seat

    this.setState({ seats })
  }

  render() {
    return (
      <div>{list.map((seat, index) => 
        <div className={`seat ${seat.status ? 'highlight' : ''}`}
             onClick={this.handleSeatClick.bind(index)}
        ></div>
      </div>
    )
  }
}

CSS:

.seat {
  background-color: #0CB607;
  border: 1px solid black;
  height: 90px;
  width: 90px;
}

.seat.highlight {
  background-color: #D70202;
}

In this example, we're persisting the array of seats in the component's state. If you are getting a pre-defined list of seats passed in, in the future, you could replace the line that creates the [...Array(5)]... bit with something that instead reads from props being passed in, or loads from an ajax call, etc.

Because the seats are persisted with their own state, as an array, we can simply inspect that state when rendering to determine whether to output the highlight CSS class - which applies the color.

One other thing you can refactor (which I didn't do, to keep this a clear explanation) is to get rid of the .bind in render entirely. Doing this is an anti-pattern, as it will re-create new functions for every item in the list, every time it renders.

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

Comments

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.