136 votes

REACT - basculer la classe sur le clic

J'essaie de comprendre comment faire basculer une classe active onClick pour modifier les propriétés CSS.

J'ai adopté de nombreuses approches et lu de nombreuses réponses de SO. En utilisant Jquery, ce serait relativement simple, mais je ne parviens pas à le faire avec React. Mon code est ci-dessous. Quelqu'un peut-il me conseiller sur la manière de procéder ?

Est-il possible de le faire sans créer un nouveau composant pour chaque élément ?

class Test extends Component(){

    constructor(props) {

    super(props);
    this.addActiveClass= this.addActiveClass.bind(this);

  }

  addActiveClass() {

    //not sure what to do here

  }

    render() {
    <div>
      <div onClick={this.addActiveClass}>
        <p>1</p>
      </div>
      <div onClick={this.addActiveClass}>
        <p>2</p>
      </div>
        <div onClick={this.addActiveClass}>
        <p>3</p>
      </div>
    </div>
  }

}

111voto

cssko Points 2033

Utilisez l'état. La documentation de Reacts est ici .

class MyComponent extends Component {
    constructor(props) {
        super(props);
        this.addActiveClass= this.addActiveClass.bind(this);
        this.state = {
            active: false,
        };
    }
    toggleClass() {
        const currentState = this.state.active;
        this.setState({ active: !currentState });
    };

    render() {
        return (
            <div 
                className={this.state.active ? 'your_className': null} 
                onClick={this.toggleClass} 
            >
                <p>{this.props.text}</p>
            </div>
        )
  }
}

class Test extends Component {
    render() {
        return (
            <div>
                <MyComponent text={'1'} />
                <MyComponent text={'2'} />
            </div>
        );
    }
}

4 votes

Y a-t-il un moyen de faire cela sans créer un composant supplémentaire ?

2 votes

Vous voulez décomposer des composants complexes en composants plus petits voir facebook.github.io/react/docs/

2 votes

J'ai décomposé le composant, mais cela ajoute toujours active à chaque élément lors du clic. Je veux qu'un seul élément ait une classe active.

30voto

Jimi Pajala Points 31

Je préfère utiliser l'opérateur "&&" sur les instructions if en ligne. À mon avis, cela donne une base de code plus propre.

En général, vous pourriez faire quelque chose comme ceci

render(){
return(
  <div>
    <button className={this.state.active && 'active'}
      onClick={ () => this.setState({active: !this.state.active}) }>Click me</button>
  </div>
)
}

Gardez à l'esprit que la fonction flèche est une fonctionnalité ES6 et n'oubliez pas de définir la valeur 'this.state.active' dans la classe constructor(){}.

this.state = { active: false }

ou si vous voulez injecter du css en JSX, vous pouvez le faire de cette manière

<button style={this.state.active && style.button} >button</button>

et vous pouvez déclarer une variable de style json

const style = { button: { background:'red' } }

n'oubliez pas d'utiliser camelCase sur les feuilles de style JSX.

16voto

EdoI Points 50

Eh bien, votre addActiveClass a besoin de savoir ce qui a été cliqué. Quelque chose comme ceci pourrait fonctionner (remarquez que j'ai ajouté les informations sur les divs qui sont actives comme un tableau d'état, et que onClick passe maintenant les informations sur ce qui a été cliqué comme un paramètre après quoi l'état est mis à jour en conséquence - il y a certainement des façons plus intelligentes de le faire, mais vous avez l'idée).

class Test extends Component(){

  constructor(props) {
    super(props);
    this.state = {activeClasses: [false, false, false]};
    this.addActiveClass= this.addActiveClass.bind(this);
  }

  addActiveClass(index) {
    const activeClasses = [...this.state.activeClasses.slice(0, index), !this.state.activeClasses[index], this.state.activeClasses.slice(index + 1)].flat();
    this.setState({activeClasses});
  }

  render() {
    const activeClasses = this.state.activeClasses.slice();
    return (
      <div>
        <div className={activeClasses[0]? "active" : "inactive"} onClick={() => this.addActiveClass(0)}>
          <p>0</p>
        </div>
        <div className={activeClasses[1]? "active" : "inactive"} onClick={() => this.addActiveClass(1)}>
          <p>1</p>
        </div>
          <div  onClick={() => this.addActiveClass(2)}>
          <p>2</p>
        </div>
      </div>
    );
  }
}

6voto

dhorelik Points 1159

React a un concept d'état des composants, donc si vous voulez le changer, faites un setState :

constructor(props) {
  super(props);

  this.addActiveClass= this.addActiveClass.bind(this);
  this.state = {
    isActive: false
  }
}

addActiveClass() {
  this.setState({
    isActive: true
  })
}

Dans votre composant, utilisez this.state.isActive pour rendre ce dont vous avez besoin.

Cela se complique lorsque vous voulez définir un état dans le composant 1 et l'utiliser dans le composant 2. Il suffit de creuser davantage dans le flux de données unidirectionnel de react et éventuellement redux qui vous aidera à le gérer.

1 votes

Je comprends state mais cela n'explique toujours pas comment mettre à jour le nom de la classe lorsqu'un élément est cliqué.

1 votes

Dans votre balisage jsx, faites - <div className={this.state.isActive ? 'active' : ''}> . Il s'agit d'un rendu conditionnel, mais qui repose toujours sur l'état.

0 votes

Mais qui ajoutera la classe active à chaque élément lors du clic. Je veux simplement que l'élément sur lequel on clique ait la classe active nom de la classe

2voto

KadoBOT Points 692

Les réponses ci-dessus fonctionneront, mais au cas où vous voudriez une approche différente, essayez classname : https://github.com/JedWatson/classnames

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X