openquestions
openquestions

Reputation: 205

react add class to child component

React newb here. Attempting to set className on (dynamically created but static in example) child element(s). Click on child and parent receives event and changes child's styles accordingly. Trivial in vanilla.js but want to know the "react way".

import React, { Component } from 'react';
import './App.css';

class App extends Component {   
  constructor(props) {
        super(props);
        this.state = { sel : "none"};
        this.handleChildClick = this.handleChildClick.bind(this);
    }
  render() {
    return (
      <div className="App">
        <header className="App-header">
            {this.state.sel}
            <div>
                <ChildClass onClick={this.handleChildClick}/>
            </div>      
        </header>
      </div>
    );
  }
  handleChildClick = (event) => {
    // console.log(event);
    // want to change background color of child by adding className
    this.setState({
        sel : event.target.innerHTML
    })  
  }
}
class ChildClass extends Component {
    constructor(props) {
        super(props);
    }
    render() {
        return (
            <div onClick={this.props.onClick}>
                div or li or button
            </div>
        )
    }
}
export default App;

-------- EDIT ----

Simple javascript version - looking for pure react way

<html>
<head>
<style>
div {
    border: 1px solid black;
    display: inline-block;
    margin-right: 10px;
    padding: 2px 4px;
}
.selected {
    background-color: #09f;
}
</style>
</head>
<body>
<div id="d_1" class='clk'>one</div>
<div id="d_2" class='clk'>two</div>
<div id="d_3" class='clk'>three</div>

<script>
let ele = document.querySelectorAll('.clk');
ele.forEach(function(e,v,t) {
    e.onclick = setThis;
});
var sel = '';
function setThis(e) {
    if(sel.length > 0) {
        document.getElementById(sel).classList.remove('selected');
    }
    document.getElementById(e.target.id).classList.add('selected');
    sel = e.target.id;
}

</script>
</body>
</html>

Upvotes: 0

Views: 6055

Answers (2)

devserkan
devserkan

Reputation: 17608

I don't know if this is what you want exactly, but here is a very simple example.

class App extends React.Component {
  state = { childClass: "" };

  handleChildClick = e =>
    this.setState( {
      childClass: e.target.innerHTML,
    } );

  render() {
    return (
      <div className="App">
        <ChildClass
          childClass={this.state.childClass}
          onClick={this.handleChildClick}
        />
      </div>
    );
  }
}

const ChildClass = props => (
  <div onClick={props.onClick} className={props.childClass}>
    <li>blue</li>
    <li>red</li>
    <li>yellow</li>
  </div>
);

ReactDOM.render( <App />, document.getElementById( "root" ) );
.blue {
  background-color: blue;
}

.red {
  background-color: red;
}

.yellow {
  background-color: yellow;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div id="root"></div>

Update after comments

Here is the example according to your pure JS code if I understand it right :) I'm using a hardcoded div list here as you can see. This is because I don't know how will you generate your divs. Maybe you will get them from an array. If this is so this code will be much more practical. Map through the array and create the divs according to their id's and so on. But, here is the hardcoded version.

class App extends React.Component {
  state = { selected: "" };

  handleChildClick = e => this.setState( { selected: e.target.id } );

  render() {
    return (
      <div className="App">
        <ChildClass
          selected={this.state.selected}
          onClick={this.handleChildClick}
        />
      </div>
    );
  }
}

const ChildClass = props => (
  <div>
    <div
      id="d_1"
      onClick={props.onClick}
      className={props.selected === "d_1" ? "clk" : ""}
    >
      one
    </div>
    <div
      id="d_2"
      onClick={props.onClick}
      className={props.selected === "d_2" ? "clk" : ""}
    >
      two
    </div>
    <div
      id="d_3"
      onClick={props.onClick}
      className={props.selected === "d_3" ? "clk" : ""}
    >
      three
    </div>
  </div>
);

ReactDOM.render( <App />, document.getElementById( "root" ) );
.clk {
  background-color: red;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div id="root"></div>

Here is the map version of how you can generate divs maybe.

const ChildClass = ( props ) => {
  const divs = [
    { id: "d_1", text: "one" },
    { id: "d_2", text: "two" },
    { id: "d_3", text: "three" },
  ];
  return (
    <div>
      {divs.map( el => (
        <div
          key={el.id}
          onClick={props.onClick}
          id={el.id}
          className={props.selected === el.id ? "clk" : ""}
        >
          {el.text}
        </div>
      ) )}
    </div>
  );
};

Upvotes: 2

vhflat
vhflat

Reputation: 589

 <ChildClass
onClick={this.handleChildClick}
className={this.state.sel}
/>

And you have to add className={this.props.className} to your div in ChildClass

Upvotes: 0

Related Questions