Afficher ou masquer un élément dans React

Je joue avec React.js pour la première fois et je ne trouve aucun moyen de montrer ou de cacher quelque chose sur une page via un événement de clic. Je ne charge aucune autre bibliothèque sur la page. Je recherche donc une manière native d’utiliser la bibliothèque React. C’est ce que j’ai jusqu’ici. Je voudrais montrer les résultats div lorsque l’événement clic se déclenche.

var Search= React.createClass({ handleClick: function (event) { console.log(this.prop); }, render: function () { return ( 
); } }); var Results = React.createClass({ render: function () { return (
Some Results
); } }); React.renderComponent( , document.body);

La clé est de mettre à jour l’état du composant dans le gestionnaire de clic à l’aide de setState . Lorsque les changements d’état sont appliqués, la méthode de 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 ( 
{ this.state.showResults ? : null }
); } }); var Results = React.createClass({ render: function() { return (
Some Results
); } }); ReactDOM.render(, document.getElementById('container'));

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

  
 render: function() { return ( 
This will be hidden if you set props.shouldHide to something truthy.
); }

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

 { this.state.showMyComponent ?  : null } 

est équivalent à:

 { this.state.showMyComponent &&  } 

Lean pourquoi


Egalement une syntaxe alternative avec display: 'none';

  

Cependant, si vous utilisez trop d’ display: 'none' , cela entraîne une pollution DOM et ralentit votre application.

Voici mon approche en utilisant ES6. Bien que la réponse acceptée soit correcte, elle est assez dépassée.

 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() { // check if box is currently opened const { isOpened } = this.state; this.setState({ // toggle value of `opened` isOpened: !opened, }); } render() { const { title, children } = this.props; const { isOpened } = this.state; return ( 
{title}
{isOpened && children && (
{children}
)}
); } } ReactDOM.render((
Some content
), 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’append des classes CSS avec display: none . Si vous définissez display: none – l’élément est toujours rendu par react et ajouté à DOM – ce qui peut avoir un impact négatif sur les performances.

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

Dans le code ci-dessus, pour ce faire, j’utilise du code comme:

 {opened && } 

Cela rendra un SomeElement seulement s’il est opened est vrai. Cela fonctionne en raison 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 ssortingng'; // will output 'some ssortingng' opened && ; // will output SomeElement if `opened` is true, will output false otherwise 

avec la version la plus récente, vous pouvez également renvoyer null pour que le contenu ne soit pas rendu.

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

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

Il définit l’atsortingbut de style à display: none !important sur la base des objects 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 ( 
); } }); var Results = React.createClass({ render: function() { return (
Some Results
); } }); React.renderComponent(, document.body);

Vous définissez une valeur booléenne dans l’état (par exemple, “show”), puis procédez comme suit:

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

Il y a déjà plusieurs excellentes réponses, mais je ne pense pas qu’elles aient été très bien expliquées et que plusieurs des méthodes proposées contiennent des pièges susceptibles de tromper les gens. Je vais donc passer en revue les trois manières principales (plus une option hors sujet) pour faire cela et expliquer les avantages et les inconvénients. J’écris surtout ceci parce que l’option 1 a été 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, sauf si vous allez seulement rendre le composant une fois et le laisser 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 rendus conditionnellement dans le parent LoginControl. Si vous lancez ceci, vous remarquerez que le constructeur est appelé sur chaque clic de 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 = ; } else { button = ; } return ( 
{button}
); } } class LogoutButton extends React.Component{ constructor(props, context){ super(props, context) console.log('created logout button'); } render(){ return ( ); } } class LoginButton extends React.Component{ constructor(props, context){ super(props, context) console.log('created login button'); } render(){ return ( ); } } function UserGreeting(props) { return

Welcome back!

; } function GuestGreeting(props) { return

Please sign up.

; } function Greeting(props) { const isLoggedIn = props.isLoggedIn; if (isLoggedIn) { return ; } return ; } ReactDOM.render( , 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, componentDidMount, render, etc. est cher, cela ralentira considérablement l’affichage du composant. Cela signifie également que vous ne pouvez pas l’utiliser avec des composants avec état dans lesquels vous souhaitez conserver l’état lorsqu’il est masqué (et restauré lorsqu’il est affiché). Le seul avantage est que le composant masqué n’est pas créé tant qu’il n’est pas sélectionné. Les composants cachés ne retarderont donc pas le chargement de votre page initiale. Il peut également y avoir des cas où vous VOULEZ qu’un composant avec état soit réinitialisé lorsqu’il est basculé. 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-circuite le rest du code de rendu si le composant est masqué. Vous pouvez également court-circuiter d’autres logiques dans d’autres méthodes en utilisant les accessoires visibles. Notez la console.log dans la page de 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 ( 
); } } class LogoutButton extends React.Component{ constructor(props, context){ super(props, context) console.log('created logout button'); } render(){ if(!this.props.isLoggedIn){ return null; } return ( ); } } class LoginButton extends React.Component{ constructor(props, context){ super(props, context) console.log('created login button'); } render(){ if(this.props.isLoggedIn){ return null; } return ( ); } } function UserGreeting(props) { return

Welcome back!

; } function GuestGreeting(props) { return

Please sign up.

; } function Greeting(props) { const isLoggedIn = props.isLoggedIn; if (isLoggedIn) { return ; } return ; } ReactDOM.render( , document.getElementById('root') );

Maintenant, si la logique d’initialisation est rapide et que les enfants sont sans état, vous ne verrez aucune différence de performance ou de fonctionnalité. Cependant, pourquoi faire de React un composant tout neuf à chaque bascule de toute façon? Si l’initialisation est coûteuse, l’option 1 l’exécutera chaque fois que vous basculez un composant qui ralentira la page lors de la commutation. L’option 2 exécute tous les inits du composant lors du premier chargement de la page. Ralentir cette première charge. Devrait noter à nouveau. Si vous affichez le composant une seule fois en fonction d’une condition et que vous ne le modifiez pas, ou si vous souhaitez le réinitialiser lors de la configuration, alors l’option 1 est correcte et constitue probablement la meilleure option.

Si le chargement lent des pages pose un problème, cela signifie que vous avez un 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 des méthodes du cycle de vie. Déplacez-le vers une fonction asynchrone lancée par ComponentDidMount et placez-le dans une variable d’état avec setState (). Si la variable d’état est nulle et que le composant est visible, la fonction de rendu doit renvoyer un espace réservé. Sinon, restituez les données. De cette façon, la page se chargera rapidement et remplira les tabs 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 les tabs chargés en premier. Ou mettez les résultats en cache et exécutez la logique uniquement 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é précédemment, il vous suffit de créer une classe CSS avec display: none et d’affecter la classe basée sur prop. L’inconvénient est que le code entier de chaque composant caché est appelé et que tous les composants caché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 plus rapide de basculer la visibilité en fonction des tests effectués par les commentateurs. d’autres réponses mais je ne peux pas en parler.

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

Celui-ci ne fonctionnera pas pour toutes les applications et il 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 pour le masquage. Disons que vous avez des tabs. Il pourrait être possible d’écrire un composant de réaction et d’utiliser simplement les accessoires pour modifier ce qui est affiché dans l’onglet. Vous pouvez également enregistrer le JSX dans les variables d’état et utiliser un prop pour décider quel JSX doit être renvoyé 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-le en tant que prop. Ou générez dans l’enfant et mettez-le en cache dans l’état de l’enfant et utilisez des accessoires pour sélectionner celui qui est actif.

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 
Hi there
; } }); ReactDOM.render( , document.getElementById('container') );

CSS

  .hide-true { display: none; } 

Violon ici

Si vous souhaitez voir comment TOGGLE l’affichage d’un composant en caisse 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 ( 

yoyoyoyoyo

); } }); ReactDOM.render( , document.getElementById('container'));

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 ; } }; 

Étendez votre propre composant:

 export const MyComp= HidableComponent(MyCompBasic); 

Ensuite, vous pouvez l’utiliser comme ceci:

   

Cela réduit un peu le temps et impose de s’en tenir aux conventions de dénomination, mais sachez que MyComp sera toujours instancié – la manière de l’omettre est mentionnée précédemment:

{ !hidden && }

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

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

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

Vous devez essentiellement afficher le composant lorsque vous cliquez sur le bouton, vous pouvez le faire de deux manières, en utilisant pure React ou en utilisant CSS, en utilisant la méthode pure React, vous pouvez faire quelque chose comme le code dans votre cas. ne s’affichent pas comme hideResults est true , mais en cliquant sur le bouton, le hideResults va changer et hideResults est false et le composant est rendu à nouveau avec les nouvelles conditions de valeur, ceci est une utilisation très courante de la modification des composants dans React …

 var Search = React.createClass({ getInitialState: function() { return { hideResults: true }; }, handleClick: function() { this.setState({ hideResults: false }); }, render: function() { return ( 
{ !this.state.hideResults && }
); } }); var Results = React.createClass({ render: function() { return (
Some Results
); } }); ReactDOM.render(, document.body);

Si vous voulez approfondir vos connaissances sur le rendu conditionnel dans React, regardez ici .

La meilleure pratique est ci-dessous selon la documentation:

  {this.state.showFooter && 
}

Rend l’élément uniquement lorsque l’état est valide.

  class FormPage extends React.Component{ constructor(props){ super(props); this.state = { hidediv: false } } handleClick = (){ this.setState({ hidediv: true }); } render(){ return( 
); } }