Il y a déjà plusieurs bonnes réponses, mais je ne pense pas qu'elles aient été très bien expliquées et plusieurs des méthodes données contiennent des pièges qui pourraient trébucher. Je vais donc passer en revue les trois principales méthodes (plus une option hors sujet) pour le faire et expliquer les avantages et les inconvénients. J'écris principalement cela parce que l'option 1 a été beaucoup 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 n'allez rendre le composant qu'une seule fois et le laisser là. Le problème est qu'il provoquera la réaction de 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 LoginControl parent. Si vous exécutez cela, vous remarquerez que le constructeur est appelé à chaque clic sur le 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 code constructeur, componentDidMount, rendu, 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 où vous souhaitez que l'état soit préservé lorsqu'il est masqué (et restauré lorsqu'il est affiché.) Le seul avantage est que le composant caché n'est pas créé du tout tant qu'il n'est pas sélectionné. Les composants cachés ne retarderont donc pas le chargement initial de votre page. Il peut également y avoir des cas où vous VOULEZ réinitialiser un composant avec état 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. Puis court-circuite le reste du code de rendu si le composant est masqué. Vous pouvez également court-circuiter d'autres logiques dans d'autres méthodes à l'aide de l'hélice visible. Remarquez 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')
);
Maintenant, si la logique d'initialisation est rapide et que les enfants sont sans état, vous ne verrez aucune différence de performances ou de fonctionnalités. Cependant, pourquoi faire en sorte que React crée un tout nouveau composant chaque bascule de toute façon? Cependant, si l'initialisation est coûteuse, l'option 1 l'exécutera à chaque fois que vous basculerez sur un composant, ce qui ralentira la page lors du basculement. L'option 2 exécutera tous les inits du composant lors du chargement de la première page. Ralentir cette première charge. Faut noter à nouveau. Si vous ne montrez le composant qu'une seule fois en fonction d'une condition et ne le changez pas, ou si vous souhaitez qu'il se réinitialise lors du basculement, l'option 1 est correcte et 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 ce n'est généralement pas une bonne idée. Vous pouvez, et devriez probablement, résoudre le lent chargement des pages en retirant le code coûteux 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 est nulle et que le composant est visible, la fonction de rendu renvoie un espace réservé. Sinon, restituez les données. De cette façon, la page se chargera rapidement et remplira les onglets lors de leur chargement. Vous pouvez également déplacer la logique dans le parent et envoyer les résultats aux enfants comme accessoires. De cette façon, vous pouvez prioriser les onglets qui seront chargés en premier. Ou mettez en cache les résultats 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 à implémenter. Comme mentionné, vous venez de créer une classe CSS avec display: none et attribuez la classe en fonction de 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 que cela soit plus rapide pour basculer 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 du tout 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 il pourrait être une meilleure solution pour certains cas d'utilisation que de masquer. Disons que vous avez des onglets. Il pourrait ê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 JSX dans des variables d'état et utiliser un accessoire pour décider quel JSX retourner 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 bon comme accessoire. Ou générer dans l'enfant et le mettre en cache dans l'état de l'enfant et utiliser des accessoires pour sélectionner celui qui est actif.