0

My state is {visibilityFilter: "completed"} or {visibilityFilter: "todo"}. Based on this I want to assign classnames to an element. Something like this,

<span {this.state.visibilityFilter=="completed"?className="active":className:""}>Completed</span>

But it's not working. I tried different variations of it,

{<span this.state.visibilityFilter=="completed"?className="active":className:"">Completed</span>}

But none of them are working. I know that it can work if I create a variable outside return statement and assign it in HTML. Like this,

let classCompleted = this.state.visibilityFilter == "completed"? "active":"";

and then,

<span className={`$(classCompleted)`}></span>

But I want to know how to do evaluate class in return statement.

Anurag Awasthi
  • 6,115
  • 2
  • 18
  • 32

2 Answers2

5

You're close, you just put the className part outside:

<span className={this.state.visibilityFilter=="completed" ? "active" : ""} onClick={this.handleFilter.bind(this,'completed')}>Completed</span>

Off-topic side note:

Using bind in the onClick every time means you'll re-bind every time that element is rendered. You might consider doing it once, in the component's constructor:

class YourComponent extends React.Component {
    constructor(...args) {
        super(...args);
        this.handleFilter = this.handleFilter.bind(this);
        // ...
    }
    handleFilter() {
        // ...
    }
    render() {
        return <span className={this.state.visibilityFilter=="completed" ? "active" : ""} onClick={this.handleFilter}>Completed</span>;
    }
}

Another option is to make it an arrow function, if you've enabled class properties in your transpiler (they're in the stage-2 preset in Babel as of this writing, January 2017):

class YourComponent extends React.Component {
    // ...
    handleFilter = event => {
        // ...
    };
    render() {
        return <span className={this.state.visibilityFilter=="completed" ? "active" : ""} onClick={this.handleFilter}>Completed</span>;
    }
}

Live example of that one:

class YourComponent extends React.Component {
    constructor() {
      super();
      this.state = {
        visibilityFilter: ""
      };
    }
    handleFilter = event => {
      this.setState({
        visibilityFilter: "completed"
      });
    };
    render() {
        return <span className={this.state.visibilityFilter == "completed" ? "active" : ""} onClick={this.handleFilter}>Completed</span>;
    }
}
ReactDOM.render(
  <YourComponent />,
  document.getElementById("react")
);
.active {
  color: blue;
}
<div id="react"></div>
<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>
T.J. Crowder
  • 1,031,962
  • 187
  • 1,923
  • 1,875
3

Use classNames, A simple javascript utility for conditionally joining classNames together.

Note: I've added the state and todo classes to demonstrate working with multiple classes. btw - the comments are not valid JSX, so don't use the code as is.

<span className={
    state: true, // always 
    active: this.state.visibilityFilter === "completed", // conditional
    todo: this.state.visibilityFilter !== "todo" // conditional
}>
Completed
</span>}

Example (based on T.J. Crowder`s code):

class YourComponent extends React.Component {
    constructor() {
      super();
      this.state = {
        visibilityFilter: ""
      };
    }
    handleFilter = event => {
      this.setState({
        visibilityFilter: "completed"
      });
    };
    render() {
        return (
          <span className={classNames({
          state: true,
          active: this.state.visibilityFilter === "completed"
        })} onClick={this.handleFilter}>Completed
        </span>
       );
    }
}
ReactDOM.render(
  <YourComponent />,
  document.getElementById("react")
);
.state {
  color: red;
  cursor: pointer;
}

.active {
  color: blue;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/classnames/2.2.5/index.min.js"></script>
<div id="react"></div>
<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>
Community
  • 1
  • 1
Ori Drori
  • 183,571
  • 29
  • 224
  • 209