web-dev-qa-db-fra.com

Afficher ou masquer un élément dans React

Je blague avec React.js pour la première fois et je ne trouve pas un moyen d'afficher ou de masquer quelque chose sur une page via un événement clic. Je ne charge aucune autre bibliothèque sur la page, je recherche donc une méthode native à l'aide de la bibliothèque React. C'est ce que j'ai jusqu'ici. Je voudrais montrer les résultats div lorsque l'événement de clic se déclenche. 

var Search= React.createClass({
    handleClick: function (event) {
        console.log(this.prop);
    },
    render: function () {
        return (
            <div className="date-range">
                <input type="submit" value="Search" onClick={this.handleClick} />
            </div>
        );
    }
});

var Results = React.createClass({
    render: function () {
        return (
            <div id="results" className="search-results">
                Some Results
            </div>
        );
    }
});

React.renderComponent(<Search /> , document.body);
343
user1725382

La clé consiste à mettre à jour l'état du composant dans le gestionnaire de clics à l'aide de setState. Lorsque les changements d'état sont appliqués, la méthode render est appelée à nouveau avec le nouvel état:

var Search = React.createClass({
    getInitialState: function() {
        return { showResults: false };
    },
    onClick: function() {
        this.setState({ showResults: true });
    },
    render: function() {
        return (
            <div>
                <input type="submit" value="Search" onClick={this.onClick} />
                { this.state.showResults ? <Results /> : null }
            </div>
        );
    }
});

var Results = React.createClass({
    render: function() {
        return (
            <div id="results" className="search-results">
                Some Results
            </div>
        );
    }
});

ReactDOM.render(<Search />, document.getElementById('container'));

http://jsfiddle.net/kb3gN/15084/

391
Douglas
<style type="text/css">
    .hidden { display:none; }
</style>
render: function() {
    return (
      <div className={this.props.shouldHide ? 'hidden' : ''}>
        This will be hidden if you set <tt>props.shouldHide</tt> 
        to something truthy.
      </div>
    );
}
166
John Haugeland

Voici une syntaxe alternative pour l'opérateur ternaire: 

{ this.state.showMyComponent ? <MyComponent /> : null }

est équivalent à:

{ this.state.showMyComponent && <MyComponent /> }

Lean pourquoi


Autre syntaxe alternative avec display: 'none';

<MyComponent style={this.state.showMyComponent ? {} : { display: 'none' }} />

Toutefois, si vous en abusez, utilisez display: 'none', ce qui entraînera une pollution par les DOM et finira par ralentir votre application.

79
Lyubomir

Voici mon approche utilisant ES6. Bien que la réponse acceptée soit correcte, elle est plutôt obsolète.

import React, { Component } from 'react';
// you should use ReactDOM.render instad of React.renderComponent
import ReactDOM from 'react-dom';

class ToggleBox extends Component {
  constructor(props) {
    super(props);
    this.state = {
      // toggle box is closed initially
      isOpened: false,
    };
    // http://egorsmirnov.me/2015/08/16/react-and-es6-part3.html
    this.toggleBox = this.toggleBox.bind(this);
  }

  toggleBox() {
    this.setState(oldState => ({ isOpened: !oldState.isOpened }));
  }

  render() {
    const { title, children } = this.props;
    const { isOpened } = this.state;
    return (
      <div className="box">
        <div className="boxTitle" onClick={this.toggleBox}>
          {title}
        </div>
        {isOpened && children && (
          <div className="boxContent">
            {children}
          </div>
        )}
      </div>
    );
  }
}

ReactDOM.render((
  <ToggleBox title="Click me">
    <div>Some content</div>
  </ToggleBox>
), document.getElementById('app'));

Démo: http://jsfiddle.net/kb3gN/16688/

Il est préférable de rendre certains éléments uniquement si nécessaire plutôt que d'ajouter des classes CSS avec display: none. Si vous définissez display: none - l'élément est toujours restitué par react et ajouté à DOM - cela peut avoir un impact négatif sur les performances. 

Imaginez que vous ayez une page avec des onglets, où chaque onglet a beaucoup de contenu et où un seul onglet est ouvert à la fois. Il est bien préférable de ne garder dans la DOM que les éléments supposés être affichés.

Dans le code ci-dessus, j'utilise un code tel que:

{opened && <SomeElement />}

Cela rendra SomeElement uniquement si opened est vrai. Cela fonctionne à cause de la façon dont JavaScript résout les conditions logiques:

true && true && 2; // will output 2
true && false && 2; // will output false
true && 'some string'; // will output 'some string'
opened && <SomeElement />; // will output SomeElement if `opened` is true, will output false otherwise
38
pie6k

avec la dernière version, réagissez 0.11, vous pouvez également renvoyer null pour qu’aucun contenu ne soit restitué.

https://facebook.github.io/react/blog/2014/07/13/react-v0.11-rc1.html#rendering-to-null

15
squiddle

J'ai créé un petit composant qui gère cela pour vous: https://www.npmjs.com/package/react-toggle-display

Il définit l'attribut de style sur display: none !important en fonction des accessoires hide ou show

Exemple d'utilisation:

var ToggleDisplay = require('react-toggle-display');

var Search = React.createClass({
    getInitialState: function() {
        return { showResults: false };
    },
    onClick: function() {
        this.setState({ showResults: true });
    },
    render: function() {
        return (
            <div>
                <input type="submit" value="Search" onClick={this.onClick} />
                <ToggleDisplay show={this.state.showResults}>
                    <Results />
                </ToggleDisplay>
            </div>
        );
    }
});

var Results = React.createClass({
    render: function() {
        return (
            <div id="results" className="search-results">
                Some Results
            </div>
        );
    }
});

React.renderComponent(<Search />, document.body);
10
ccnokes

Vous définissez une valeur booléenne dans l'état (par exemple, "show"), puis faites:

var style = {};
if (!this.state.show) {
  style.display = 'none'
}

return <div style={style}>...</div>
9
FakeRainBrigand

Il y a déjà plusieurs bonnes réponses, mais je ne pense pas qu'elles ont été très bien expliquées et plusieurs des méthodes données contiennent des pièges qui pourraient faire trébucher les gens. Je vais donc passer en revue les trois manières principales (plus une option hors sujet) de le faire et d’expliquer le pour et le contre. J'écris principalement ceci parce que l'option 1 a été fortement recommandée et qu'il y a beaucoup de problèmes potentiels avec cette option si elle n'est pas utilisée correctement.

Option 1: rendu conditionnel dans le parent.

Je n'aime pas cette méthode, à moins que vous ne rendiez le composant qu'une seule fois et le laissiez là. Le problème est que cela provoquera une réaction pour créer le composant à partir de zéro chaque fois que vous basculez la visibilité ..Voici l'exemple. LogoutButton ou LoginButton sont restitués de manière conditionnelle dans le parent LoginControl. Si vous exécutez ceci, vous remarquerez que le constructeur est appelé à chaque clic sur un bouton. https://codepen.io/Kelnor/pen/LzPdpN?editors=1111

class LoginControl extends React.Component {
  constructor(props) {
    super(props);
    this.handleLoginClick = this.handleLoginClick.bind(this);
    this.handleLogoutClick = this.handleLogoutClick.bind(this);
    this.state = {isLoggedIn: false};
  }

  handleLoginClick() {
    this.setState({isLoggedIn: true});
  }

  handleLogoutClick() {
    this.setState({isLoggedIn: false});
  }

  render() {
    const isLoggedIn = this.state.isLoggedIn;

    let button = null;
    if (isLoggedIn) {
      button = <LogoutButton onClick={this.handleLogoutClick} />;
    } else {
      button = <LoginButton onClick={this.handleLoginClick} />;
    }

    return (
      <div>
        <Greeting isLoggedIn={isLoggedIn} />
        {button}
      </div>
    );
  }
}

class LogoutButton extends React.Component{
  constructor(props, context){
    super(props, context)
    console.log('created logout button');
  }
  render(){
    return (
      <button onClick={this.props.onClick}>
        Logout
      </button>
    );
  }
}

class LoginButton extends React.Component{
  constructor(props, context){
    super(props, context)
    console.log('created login button');
  }
  render(){
    return (
      <button onClick={this.props.onClick}>
        Login
      </button>
    );
  }
}

function UserGreeting(props) {
  return <h1>Welcome back!</h1>;
}

function GuestGreeting(props) {
  return <h1>Please sign up.</h1>;
}

function Greeting(props) {
  const isLoggedIn = props.isLoggedIn;
  if (isLoggedIn) {
    return <UserGreeting />;
  }
  return <GuestGreeting />;
}

ReactDOM.render(
  <LoginControl />,
  document.getElementById('root')
);

Maintenant, React est assez rapide pour créer des composants à partir de zéro. Cependant, il doit toujours appeler votre code lors de sa création. Donc, si votre constructeur, composantDidMount, rendu, etc. code est cher, il ralentira considérablement l'affichage du composant. Cela signifie également que vous ne pouvez pas utiliser ceci avec des composants avec état où vous souhaitez que l'état soit préservé lorsqu'il est masqué (et restauré lorsqu'il est affiché). L'avantage est que le composant masqué n'est pas créé du tout jusqu'à ce qu'il soit sélectionné. Ainsi, les composants cachés ne retarderont pas le chargement initial de votre page. Il se peut également que vous souhaitiez réinitialiser un composant avec état lorsque vous le basculez. Dans ce cas, c'est votre meilleure option.

Option 2: rendu conditionnel chez l'enfant

Cela crée les deux composants une fois. Ensuite, court-circuitez le reste du code de rendu si le composant est masqué. Vous pouvez également court-circuiter d'autres logiques dans d'autres méthodes en utilisant l'accessoire visible. Notez le fichier console.log dans la page codepen. https://codepen.io/Kelnor/pen/YrKaWZ?editors=0011

class LoginControl extends React.Component {
  constructor(props) {
    super(props);
    this.handleLoginClick = this.handleLoginClick.bind(this);
    this.handleLogoutClick = this.handleLogoutClick.bind(this);
    this.state = {isLoggedIn: false};
  }

  handleLoginClick() {
    this.setState({isLoggedIn: true});
  }

  handleLogoutClick() {
    this.setState({isLoggedIn: false});
  }

  render() {
    const isLoggedIn = this.state.isLoggedIn;
    return (
      <div>
        <Greeting isLoggedIn={isLoggedIn} />
        <LoginButton isLoggedIn={isLoggedIn} onClick={this.handleLoginClick}/>
        <LogoutButton isLoggedIn={isLoggedIn} onClick={this.handleLogoutClick}/>
      </div>
    );
  }
}

class LogoutButton extends React.Component{
  constructor(props, context){
    super(props, context)
    console.log('created logout button');
  }
  render(){
    if(!this.props.isLoggedIn){
      return null;
    }
    return (
      <button onClick={this.props.onClick}>
        Logout
      </button>
    );
  }
}

class LoginButton extends React.Component{
  constructor(props, context){
    super(props, context)
    console.log('created login button');
  }
  render(){
    if(this.props.isLoggedIn){
      return null;
    }
    return (
      <button onClick={this.props.onClick}>
        Login
      </button>
    );
  }
}

function UserGreeting(props) {
  return <h1>Welcome back!</h1>;
}

function GuestGreeting(props) {
  return <h1>Please sign up.</h1>;
}

function Greeting(props) {
  const isLoggedIn = props.isLoggedIn;
  if (isLoggedIn) {
    return <UserGreeting />;
  }
  return <GuestGreeting />;
}

ReactDOM.render(
  <LoginControl />,
  document.getElementById('root')
);

Désormais, si la logique d'initialisation est rapide et que les enfants sont sans état, vous ne verrez aucune différence en termes de performances ou de fonctionnalités. Cependant, pourquoi React crée-t-il un tout nouveau composant à chaque bascule? Si l'initialisation est coûteuse, Option 1 l'exécutera à chaque fois que vous basculerez sur un composant, ce qui ralentira la page lors de la commutation. L'option 2 lancera toutes les entrées du composant lors du chargement de la première page. Ralentir ce premier chargement. Devrait noter à nouveau. Si vous ne montrez qu'une seule fois le composant en fonction d'une condition et que vous ne le basculez pas, ou si vous souhaitez le réinitialiser lorsqu'il est basculé, l'option 1 convient et constitue probablement la meilleure option.

Si le chargement lent des pages pose problème, cela signifie que vous avez du code coûteux dans une méthode de cycle de vie et que ce n'est généralement pas une bonne idée. Vous pouvez et devriez probablement résoudre le chargement de page lent en déplaçant le code coûteux hors des méthodes de cycle de vie. Déplacez-le vers une fonction asynchrone lancée par ComponentDidMount et demandez au rappel de le placer dans une variable d'état avec setState (). Si la variable d'état a la valeur null et que le composant est visible, faites en sorte que la fonction de rendu renvoie un espace réservé. Sinon restituer les données. De cette façon, la page se chargera rapidement et remplira les onglets au fur et à mesure de leur chargement. Vous pouvez également déplacer la logique dans le parent et transmettre les résultats aux enfants comme accessoires. De cette façon, vous pouvez hiérarchiser quels onglets sont chargés en premier. Ou cachez les résultats et n'exécutez la logique que la première fois qu'un composant est affiché.

Option 3: masquage de classe

Le masquage de classe est probablement le plus facile à mettre en œuvre. Comme mentionné, vous créez simplement une classe CSS avec display: none et assignez la classe en fonction de prop. L'inconvénient est que tout le code de chaque composant masqué est appelé et que tous les composants masqués sont attachés au DOM. (L'option 1 ne crée pas du tout les composants cachés. Et l'option 2 court-circuite le code inutile lorsque le composant est masqué et supprime complètement le composant du DOM.) Il semble que cela permette de basculer plus rapidement la visibilité selon certains tests effectués par des commentateurs sur d'autres réponses mais je ne peux pas en parler.

Option 4: Un composant mais changez les accessoires. Ou peut-être aucun composant et cache HTML.

Celle-ci ne fonctionnera pas pour toutes les applications et est hors sujet car il ne s'agit pas de masquer des composants, mais cela pourrait être une meilleure solution pour certains cas d'utilisation que de masquer. Disons que vous avez des onglets. Il serait peut-être possible d'écrire un composant React et d'utiliser simplement les accessoires pour changer ce qui est affiché dans l'onglet. Vous pouvez également enregistrer le fichier JSX dans des variables d'état et utiliser un accessoire pour déterminer le fichier JSX à renvoyer dans la fonction de rendu. Si le JSX doit être généré, faites-le et mettez-le en cache dans le parent et envoyez celui qui convient comme accessoire. Ou générer dans l'enfant et le mettre en cache dans son état et utiliser les accessoires pour sélectionner celui qui est actif.

7
Kelnor

C'est un bon moyen d'utiliser le DOM virtuel:

Réagir:

            var Comp = React.createClass({
                getInitialState: function(){
                return {hide: false};
              },
              toggle: function(){
                this.setState({hide: !this.state.hide});
              },
              render: function() {
                return <div>
                        <button onClick={this.toggle}>toggle</button>    
                    <div className={'hide-' + this.state.hide}>Hi there</div>
                </div>;
              }
            });

            ReactDOM.render(
              <Comp />,
              document.getElementById('container')
            );

CSS

            .hide-true  {
              display: none;
            }

Violon ici

5
daniloprates

La meilleure pratique est ci-dessous selon la documentation:

 {this.state.showFooter && <Footer />}

Rendez l'élément uniquement lorsque l'état est valide.

3
Dynamic
   class FormPage extends React.Component{
      constructor(props){
           super(props);
           this.state = {
             hidediv: false
           }
      }

     handleClick = (){
       this.setState({
          hidediv: true
        });
      }

      render(){
        return(
        <div>
          <div className="date-range" hidden = {this.state.hidediv}>
               <input type="submit" value="Search" onClick={this.handleClick} />
          </div>
          <div id="results" className="search-results" hidden = {!this.state.hidediv}>
                        Some Results
           </div>
        </div>
        );
      }
  }
3
Akanksha gore

Si vous souhaitez voir comment basculer l'affichage d'un composant extrait ce violon.

http://jsfiddle.net/mnoster/kb3gN/16387/

var Search = React.createClass({
    getInitialState: function() {
        return { 
            shouldHide:false
        };
    },
    onClick: function() {
        console.log("onclick");
        if(!this.state.shouldHide){
            this.setState({
                shouldHide: true 
            })
        }else{
                    this.setState({
                shouldHide: false 
            })
        }
    },
render: function() {
    return (
      <div>
        <button onClick={this.onClick}>click me</button>
        <p className={this.state.shouldHide ? 'hidden' : ''} >yoyoyoyoyo</p>
      </div>
    );
}
});

ReactDOM.render( <Search /> , document.getElementById('container'));
3
Nicholas

Dans certains cas, un composant d'ordre supérieur peut être utile:

Créer un composant d'ordre supérieur:

export var HidableComponent = (ComposedComponent) => class extends React.Component {
    render() {
        if ((this.props.shouldHide!=null && this.props.shouldHide()) || this.props.hidden)
            return null;
        return <ComposedComponent {...this.props}  />;
    }
};

Étendez votre propre composant:

export const MyComp= HidableComponent(MyCompBasic);

Ensuite, vous pouvez l'utiliser comme ceci:

<MyComp hidden={true} ... />
<MyComp shouldHide={this.props.useSomeFunctionHere} ... />

Cela réduit un peu le poids et impose de respecter les conventions de nommage, mais sachez que MyComp sera toujours instancié - la façon d'omettre est mentionnée plus haut:

{ !hidden && <MyComp ... /> }

2
vinga

Je commence par cette déclaration de l'équipe de React:

Dans React, vous pouvez créer des composants distincts qui encapsulent le comportement vous avez besoin. Ensuite, vous ne pouvez en rendre que certains, en fonction du état de votre application.

Le rendu conditionnel dans React fonctionne de la même manière que les conditions dans JavaScript. Utilisez des opérateurs JavaScript comme si ou le conditionnel opérateur pour créer des éléments représentant l’état actuel et laisser Réagissez mettre à jour l'interface utilisateur pour les faire correspondre.

En gros, vous devez afficher le composant lorsque le bouton est cliqué. Vous pouvez le faire de deux manières, en utilisant purement React ou en CSS, en utilisant purement React, vous pouvez faire quelque chose comme le code ci-dessous dans votre cas. Ainsi, lors de la première exécution, ne sont pas affichés car hideResults est true, mais en cliquant sur le bouton, l'état va changer et hideResults est false et le composant est rendu à nouveau avec les nouvelles conditions de valeur, il est très courant de changer la vue du composant dans React ...

var Search = React.createClass({
  getInitialState: function() {
    return { hideResults: true };
  },

  handleClick: function() {
    this.setState({ hideResults: false });
  },

  render: function() {
    return (
      <div>
        <input type="submit" value="Search" onClick={this.handleClick} />
        { !this.state.hideResults && <Results /> }
      </div> );
  }

});

var Results = React.createClass({
  render: function() {
    return (
    <div id="results" className="search-results">
      Some Results
    </div>);
   }
});

ReactDOM.render(<Search />, document.body);

Si vous souhaitez approfondir vos connaissances sur le rendu conditionnel dans React, consultez ici .

2
Alireza

Utilisez cette syntaxe maigre et courte:

{ this.state.show && <MyCustomComponent /> }
1
Zain Ul Hassan

Utilisez ref et manipulez CSS

Une solution pourrait être d'utiliser ref de React et de manipuler la classe CSS à l'aide de l'API du navigateur. Son avantage est d’éviter la restitution dans React si le seul but est de masquer/afficher un élément DOM en un seul clic.

// Parent.jsx
import React, { Component } from 'react'

export default class Parent extends Component {
    constructor () {    
        this.childContainer = React.createRef()
    }

    toggleChild = () => {
        this.childContainer.current.classList.toggle('hidden')
    }

    render () {
        return (
            ...

            <button onClick={this.toggleChild}>Toggle Child</button>
            <div ref={this.childContainer}>
                <SomeChildComponent/>
            </div>

            ...
        );
    }
}


// styles.css
.hidden {
    display: none;
}

PS Corrigez-moi si je me trompe.)

1
UtkarshPramodGupta

Ceci peut aussi être réalisé comme ça (moyen très simple)

 class app extends Component {
   state = {
     show: false
   };
 toggle= () => {
   var res = this.state.show;
   this.setState({ show: !res });
 };
render() {
  return(
   <button onClick={ this.toggle }> Toggle </button>
  {
    this.state.show ? (<div> HELLO </div>) : null
  }
   );
     }
1
basitmir

Vous pouvez utiliser le fichier css

    var Results = React.createClass({
    render: function() {
        return (
            <div id="results" className={`search-results ${this.state.showResults ? 'show' : ''}`}>
                Some Results
            </div>
        );
    }
})

et dans le fichier css

    .search-results {
     ...
     display: none
     &.show {
      display: block
   }
}
0
arco

cet exemple montre comment passer d’un composant à l’autre en utilisant une bascule qui change toutes les secondes 

import React ,{Fragment,Component} from "react";
import ReactDOM from "react-dom";

import "./styles.css";

const Component1 = () =>(
  <div>
    <img 
src="https://i.pinimg.com/originals/58/df/1d/58df1d8bf372ade04781b8d4b2549ee6.jpg" />
   </div>
)

const Component2 = () => {
  return (
    <div>
       <img 
src="http://www.chinabuddhismencyclopedia.com/en/images/thumb/2/2e/12ccse.jpg/250px- 
12ccse.jpg" />
  </div>
   )

 }

 class App extends Component {
   constructor(props) {
     super(props);
    this.state = { 
      toggleFlag:false
     }
   }
   timer=()=> {
    this.setState({toggleFlag:!this.state.toggleFlag})
  }
  componentDidMount() {
    setInterval(this.timer, 1000);
   }
  render(){
     let { toggleFlag} = this.state
    return (
      <Fragment>
        {toggleFlag ? <Component1 /> : <Component2 />}
       </Fragment>
    )
  }
}


const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);
0
Snivio

Si vous utilisez bootstrap 4, vous pouvez cacher un élément de cette façon

className={this.state.hideElement ? "invisible" : "visible"}
0
ThomasP1988
var Search= React.createClass({
 getInitialState: () => { showResults: false },
 onClick: () => this.setState({ showResults: true }),
 render: function () {
   const { showResults } = this.state;
   return (
     <div className="date-range">
       <input type="submit" value="Search" onClick={this.handleClick} />
       {showResults && <Results />}
     </div>
   );
 }
});

var Results = React.createClass({
    render: function () {
        return (
            <div id="results" className="search-results">
                Some Results
            </div>
        );
    }
});

React.renderComponent(<Search /> , document.body);
0
Alan Paul Mathew

Utilisez rc-if-else module

npm install --save rc-if-else
import React from 'react';
import { If } from 'rc-if-else';

class App extends React.Component {
    render() {
        return (
            <If condition={this.props.showResult}>
                Some Results
            </If>
        );
    }
}
0
qinyuanbin