Search code examples
cssreactjsdictionarysetstateclassname

React JS: how to change the bgcolor of a div in a group of divs based on another element's className bgcolor style


setup: i have dynamically generated two independent groups of divs. First group of divs represents 4 different bgcolor styles [named ArticlePreview] and the second group represents 4 partial examples of cells within an eventually grid-like structure [ named ArticleCells].

result wanted: when a user clicks on one of the articles to select it, the user should then be able to go and click on one or multiple cells and apply that same style of bgcolor as of the selected article and if no article is selected, then the default bgcolor are applied for both article and cell elements.

sandbox: code sample

code sample:

const ArticlePreview = props => {
  return (
    <div className={props.class} onClick={props.onClick}>
      {props.article}
    </div>
  );
};

const ArticleCells = props => {
  return (
    <div className={props.class} onClick={props.onClick}>
      {props.cell}
    </div>
  );
};
class App extends React.Component {
  constructor(props) {
    super(props);

    this.state = {
      selected: false,
      article: "",
      cell: "",
      class: ""
    };
  }

  onSelectArticle = article => {
    this.setState({
      selected: true,
      article: article
    });
  };

  onSelectCell = cell => {

    var style = (cell.currentTarget.style.backgroundColor =
      this.state.selected && this.state.cell === cell ? "bkcolor" : "default");
    this.setState({
      selected: true,
      cell: cell,
      class: { style }
    });
  };

  render() {
    let articles = ["Article 1", "Article 2", "Article 3", "Article 4"];
    let cells = ["Div 1", "Div 2", "Div 3", "Div 4"];

    return (
      <div>
        <div>
          {articles.map((article, index) => (
            <ArticlePreview
              key={index}
              class={
                this.state.selected &&
                this.state.article === article &&
                this.state.article === articles[0]
                  ? "bkcolorGreen"
                  : this.state.selected &&
                    this.state.article === article &&
                    this.state.article === articles[1]
                  ? "bkcolorBlue"
                  : this.state.selected &&
                    this.state.article === article &&
                    this.state.article === articles[2]
                  ? "bkcolorOrange"
                  : this.state.selected &&
                    this.state.article === article &&
                    this.state.article === articles[3]
                  ? "bkcolorYellow"
                  : "default"
              }
              onClick={() => this.onSelectArticle(article)}
              article={article}
            />
          ))}
        </div>
        <br />
        <div>
          {cells.map((cell, index) => (
            <ArticleCells
              key={index}
              class={this.state.class}
              onClick={cell => this.onSelectCell(cell)}
              cell={cell}
            />
          ))}
        </div>
      </div>
    );
  }
}

Solution

  • This is an update for the above snippet, @punch this will help you Sandbox Link. Please go through it and let me know if you have any issues.

    This is the updated component

    import React from "react";
    import ReactDOM from "react-dom";
    
    import "./styles.css";
    
    const ArticlePreview = props => {
      return (
        <div className={props.class} onClick={props.onClick}>
          {props.article}
        </div>
      );
    };
    
    const ArticleCells = props => {
      console.log(props.class);
      return (
        <div className={props.class} onClick={props.onClick}>
          {props.cell}
        </div>
      );
    };
    
    const articles = ["Article 1", "Article 2", "Article 3", "Article 4"];
    const cells = ["Cell 1", "Cell 2", "Cell 3", "Cell 4"];
    const colors = [
      "bkcolorGreen",
      "bkcolorBlue",
      "bkcolorOrange",
      "bkcolorYellow"
    ];
    
    class App extends React.Component {
      constructor(props) {
        super(props);
    
        this.state = {
          selected: false,
          article: "",
          cell: "",
          class: ""
        };
      }
    
      onSelectArticle = article => {
        this.setState({
          selected: true,
          article: article
        });
      };
    
      onSelectCell = cell => {
        //cell.currentTarget.style.backgroundColor = "pink";
        cell.target.removeAttribute("class");
        cell.target.classList.add(colors[articles.indexOf(this.state.article)]);
        // var style = (cell.currentTarget.classList.add(colors[articles.indexOf(this.state.article)]) && this.state.cell === cell ? "bkcolor" : "default");
        this.setState({
          selected: true,
          cell: cell
          // class: { style }
        });
      };
    
      render() {
        return (
          <div>
            <div>
              {articles.map((article, index) => (
                <ArticlePreview
                  key={index}
                  class={
                    this.state.selected && article === this.state.article
                      ? colors[articles.indexOf(this.state.article)]
                      : "default"
                  }
                  onClick={() => this.onSelectArticle(article)}
                  article={article}
                />
              ))}
            </div>
            <br />
            <div>
              {cells.map((cell, index) => (
                <ArticleCells
                  key={index}
                  class={`${this.state.class}`}
                  onClick={cell => this.onSelectCell(cell)}
                  cell={cell}
                />
              ))}
            </div>
          </div>
        );
      }
    }
    
    ReactDOM.render(<App />, document.getElementById("root"));