Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Conditionally setting className based on a state variable in a React functional component

I'm trying to change the appearance of a button based on if that element exists in state. It is a multiple selection selection. So setAnswer is called, which calls addAnswer. I then want to set the className based on whether the element is in state but I'm just not getting it.

{question.values.map(answer => {
        return  <button className="buttons" key={answer} onClick={() => addAnswer(answer)}>
        {answer}</button>
})}
const addAnswer = (answer) => {
        let indexAnswer = answers.indexOf(answer)
        if (indexAnswer > -1) {
            setAnswer((answers) => answers.filter((a) => { 
                return a != answer }))}

        else setAnswer([...answers, answer])
    };
like image 397
Jerry Garcia Avatar asked Jun 24 '20 22:06

Jerry Garcia


People also ask

How do you conditionally set a className in React?

A CSS class can be conditionally applied in React using plain JavaScript: Put all CSS classes into an array. Use a ternary operator to set an empty string as a class when the condition is false . Join the array using spaces, to convert it into a className .

Can you put a className on a React component?

To pass class names as props to a React component:Pass a string containing the class names as a prop. Destructure the prop in the child component. Assign the class names to an element, e.g. <h2 className={className}>Content</h2> .

Can you conditionally add attributes to components in React?

In React, adding attributes conditionally is frequently necessary. In React, it is pretty simple. React is sophisticated enough to skip through some properties if the value you supply is untruthful. This is helpful, mainly when adding numerous characteristics conditionally.


2 Answers

You can conditionally set a class like this

{question.values.map(answer => {
        return (<button 
                 className={answers.indexOf(answer) === -1 ? 'class1' : 'class2'} 
                 key={answer} 
                 onClick={() => addAnswer(answer)}
               >
                 {answer}
              </button> );
})}
like image 173
Siddharth Avatar answered Oct 22 '22 14:10

Siddharth


clsx is the perfect candidate for this. You can conditionaly set one or more classNames which get used if a condition is true.

Here's a real working snippet I made which is also available here https://codesandbox.io/s/gracious-sound-2d5fr?file=/src/App.js

import React from "react";
import "./styles.css";
import clsx from "clsx";

import { createUseStyles } from "react-jss";

// Create your Styles. Remember, since React-JSS uses the default preset,
// most plugins are available without further configuration needed.
const useStyles = createUseStyles({
  answer1: { color: "red" },
  answer2: { color: "green" },
  answer3: { color: "yellow" }
});

export default function App() {
  const classes = useStyles();

  const questions = {
    values: [
      { type: 1, value: "aaaa" },
      { type: 2, value: "bbbb" },
      { type: 3, value: "cccc" },
      { type: 1, value: "dddd" },
      { type: 2, value: "eeee" },
      { type: 3, value: "ffff" }
    ]
  };

  return (
    <div className="App">
      {questions.values.map(answer => (
        <p>
          <button
            className={clsx(classes.always, {
              [classes.answer1]: answer.type === 1,
              [classes.answer2]: answer.type === 2,
              [classes.answer3]: answer.type === 3
            })}
          >
            {answer.value}
          </button>
        </p>
      ))}
    </div>
  );
}

for more information on clsx see this example here Understanding usage of clsx in React

Alternatively you can determine the class name via logic and set it in a variable like this

const getClassName = ()=> { 

  switch(answer) {
    case(1): return "class1"
    case(2): return "class2"
    ...
  }
   
}

render(
  /// within the map function
  <   className={getClassName()}  />
)

like image 43
Max Carroll Avatar answered Oct 22 '22 12:10

Max Carroll