Ci sono già molte risposte fantastiche, ma non credo che siano state spiegate molto bene e molti dei metodi forniti contengono alcuni trucchi che potrebbero far inciampare le persone. Quindi esaminerò i tre modi principali (più un'opzione off-topic) per fare questo e spiegare i pro ei contro. Lo scrivo principalmente perché l'opzione 1 è stata raccomandata molto e ci sono molti potenziali problemi con quell'opzione se non usata correttamente.
Opzione 1: rendering condizionale nel genitore.
Non mi piace questo metodo a meno che tu non voglia renderizzare il componente una sola volta e lasciarlo lì. Il problema è che farà reagire creando il componente da zero ogni volta che si attiva / disattiva la visibilità. Ecco l'esempio. LogoutButton o LoginButton vengono sottoposti a rendering condizionale nel LoginControl padre. Se esegui questo, noterai che il costruttore viene chiamato su ogni clic del pulsante. 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')
);
Ora React è abbastanza veloce nel creare componenti da zero. Tuttavia, deve ancora chiamare il codice durante la creazione. Quindi se il tuo costruttore, componentDidMount, render, ecc. Codice è costoso, allora rallenterà in modo significativo mostrando il componente. Significa anche che non è possibile utilizzarlo con componenti con stato in cui si desidera conservare lo stato quando nascosto (e ripristinato quando visualizzato). L'unico vantaggio è che il componente nascosto non viene creato fino a quando non viene selezionato. Quindi i componenti nascosti non ritarderanno il caricamento della pagina iniziale. Ci possono anche essere casi in cui VUOI reimpostare un componente con stato per ripristinare quando attivato. Nel qual caso questa è la tua migliore opzione.
Opzione 2: rendering condizionale nel bambino
Questo crea entrambi i componenti una volta. Quindi cortocircuita il resto del codice di rendering se il componente è nascosto. Puoi anche cortocircuitare altre logiche in altri metodi usando il puntello visibile. Notare console.log nella pagina 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')
);
Ora, se la logica di inizializzazione è rapida e i figli sono apolidi, allora non vedrai alcuna differenza in termini di prestazioni o funzionalità. Tuttavia, perché fare in modo che React crei un nuovo componente ogni interruttore? Se l'inizializzazione è costosa, l'opzione 1 verrà eseguita ogni volta che si attiva o disattiva un componente che rallenta la pagina quando si cambia. L'opzione 2 eseguirà tutti gli init del componente al caricamento della prima pagina. Rallentando quel primo carico. Dovrebbe notare di nuovo. Se stai solo mostrando il componente una volta in base a una condizione e non attivandolo o se vuoi che venga ripristinato quando attivato, l'opzione 1 va bene e probabilmente l'opzione migliore.
Se il caricamento lento della pagina è comunque un problema, significa che hai un codice costoso in un metodo del ciclo di vita e che generalmente non è una buona idea. Puoi, e probabilmente dovresti, risolvere il lento caricamento della pagina spostando il costoso codice dai metodi del ciclo di vita. Spostalo in una funzione asincrona che è stata avviata da ComponentDidMount e fai in modo che il callback lo inserisca in una variabile di stato con setState (). Se la variabile di stato è nulla e il componente è visibile, fare in modo che la funzione di rendering restituisca un segnaposto. Altrimenti renderizza i dati. In questo modo la pagina si caricherà rapidamente e popolerà le schede mentre vengono caricate. Puoi anche spostare la logica nel genitore e inviare i risultati ai bambini come oggetti di scena. In questo modo puoi dare la priorità a quali schede vengono caricate per prime. Oppure memorizza nella cache i risultati ed esegui la logica solo la prima volta che viene mostrato un componente.
Opzione 3: nascondere la classe
Nascondere la classe è probabilmente il più facile da implementare. Come accennato, devi solo creare una classe CSS con display: none e assegnare la classe in base a prop. Il rovescio della medaglia è l'intero codice di ogni componente nascosto chiamato e tutti i componenti nascosti sono collegati al DOM. (L'opzione 1 non crea affatto i componenti nascosti. E l'opzione 2 mette in cortocircuito il codice non necessario quando il componente è nascosto e rimuove completamente il componente dal DOM.) Sembra che questo sia più veloce nel cambiare la visibilità secondo alcuni test effettuati dai commentatori su altre risposte ma non posso parlarne.
Opzione 4: un componente ma cambia i puntelli. O forse nessun componente e cache HTML.
Questo non funzionerà per tutte le applicazioni ed è fuori tema perché non si tratta di nascondere i componenti, ma potrebbe essere una soluzione migliore per alcuni casi d'uso che nascondere. Supponiamo che tu abbia delle schede. Potrebbe essere possibile scrivere un componente React e usare solo gli oggetti di scena per cambiare ciò che viene visualizzato nella scheda. È inoltre possibile salvare JSX in variabili di stato e utilizzare un prop per decidere quale JSX restituire nella funzione di rendering. Se il JSX deve essere generato, fallo e memorizzalo nella cache del genitore e invia quello corretto come prop. Oppure genera nel figlio e memorizzalo nella cache nello stato del figlio e usa i puntelli per selezionare quello attivo.