Nascondi / Mostra componenti in reagisce nativo


143

Sono davvero nuovo a React Native e mi chiedo come posso nascondere / mostrare un componente.
Ecco il mio caso di test:

<TextInput
    onFocus={this.showCancel()}
    onChangeText={(text) => this.doSearch({input: text})} />

<TouchableHighlight 
    onPress={this.hideCancel()}>
    <View>
        <Text style={styles.cancelButtonText}>Cancel</Text>
    </View>
</TouchableHighlight>

Ho un TextInputcomponente, quello che voglio è mostrare TouchableHighlightquando l'input ottiene lo stato attivo, quindi nascondere TouchableHighlightquando l'utente preme il pulsante Annulla.

Non so come "accedere" al TouchableHighlightcomponente per nasconderlo / mostrarlo all'interno delle mie funzioni showCancel/hideCancel.
Inoltre, come posso nascondere il pulsante sin dall'inizio?


Risposte:


135

Vorrei fare qualcosa del genere:

var myComponent = React.createComponent({

    getInitialState: function () {
        return {
            showCancel: false,
        };
    },

    toggleCancel: function () {
        this.setState({
            showCancel: !this.state.showCancel
        });
    }

    _renderCancel: function () {
        if (this.state.showCancel) {
            return (
                <TouchableHighlight 
                    onPress={this.toggleCancel()}>
                    <View>
                        <Text style={styles.cancelButtonText}>Cancel</Text>
                    </View>
                </TouchableHighlight>
            );
        } else {
            return null;
        }
    },

    render: function () {
        return (
            <TextInput
                onFocus={this.toggleCancel()}
                onChangeText={(text) => this.doSearch({input: text})} />
            {this._renderCancel()}          
        );
    }

});

1
Grazie mille per questo, solo una piccola modifica che dovevo fare: onFocus = {() => this.showCancel ()} questa deve essere una funzione di callback.
Crysfel,

3
return ''return null
Ha

33
Puoi anche farlo {someBoolVal && <Component />}e mostrerà solo se il valore bool è vero.
Nathan Hyland,

Questa è la risposta migliore
Kirill Gusyatin,

3
Non so che questa è la risposta accettata che non implementa la funzionalità desiderata originale mostra / nascondi, ma invece aggiunge / rimuovi
Muhammad Aref

150

Nella tua funzione di rendering:

{ this.state.showTheThing && 
  <TextInput/>
}

Quindi fai semplicemente:

this.setState({showTheThing: true})  // to show it  
this.setState({showTheThing: false}) // to hide it

2
Questo ha funzionato per me. Tuttavia, non sono sicuro del motivo per cui quando faccio qualcosa come { this.state.showTheThing && (<Text>foo</Text> && <Text>bar</Text>)}solo "bar" viene mostrato nell'interfaccia utente. Mi aspetto che vengano visualizzati "pippo" e "barra". Quello che ho dovuto fare per risolvere questo è chiamare{ this.state.showTheThing && (<Text>foo</Text>} { this.state.showTheThing && (<Text>bar</Text>}
tonatiuhnb il

2
forse funziona? perché la logica &&non combina elementi{ this.state.showTheThing && (<View><Text>foo</Text><Text>bar</Text></View>)}
muescha,

Questo ha funzionato per me, volevo mostrare un pulsante "Passaggio successivo" quando un utente ha caricato la sua immagine profilo. quindi il mio codice era:{this.state.hasPic && <Button title="Go to next step" onPress={this._nextStep} />}
Daggie Blanqx - Douglas Mwangi

Per chiunque abbia difficoltà a mostrare più di un componente, avvolgi il componente con un frammento. per esempio. <React.Fragment><Text>Foo</Text><Text>Bar></Text></React.Fragment>
Ben Cull,

48

In reattivo o reattivo nativo il modo in cui il componente nascondi / mostra o aggiungi / rimuovi non funziona come in Android o iOS. Molti di noi pensano che ci sarebbe una strategia simile

View.hide = true or parentView.addSubView(childView)

Ma il modo in cui reagiscono al lavoro nativo è completamente diverso. L'unico modo per ottenere questo tipo di funzionalità è includere il componente nel DOM o rimuoverlo dal DOM.

Qui in questo esempio ho intenzione di impostare la visibilità della visualizzazione del testo in base al clic sul pulsante.

inserisci qui la descrizione dell'immagine

L'idea alla base di questa attività è la creazione di una variabile di stato chiamata state con il valore iniziale impostato su false quando si verifica l'evento click del pulsante, quindi il valore si attiva / disattiva. Ora useremo questa variabile di stato durante la creazione del componente.

import renderIf from './renderIf'

class FetchSample extends Component {
  constructor(){
    super();
    this.state ={
      status:false
    }
  }

  toggleStatus(){
    this.setState({
      status:!this.state.status
    });
    console.log('toggle button handler: '+ this.state.status);
  }

  render() {
    return (
      <View style={styles.container}>
        {renderIf(this.state.status)(
          <Text style={styles.welcome}>
            I am dynamic text View
          </Text>
        )}

        <TouchableHighlight onPress={()=>this.toggleStatus()}>
          <Text>
            touchme
          </Text>
        </TouchableHighlight>
      </View>
    );
  }
}

l'unica cosa da notare in questo frammento è renderIfche in realtà è una funzione che restituirà il componente passato ad esso in base al valore booleano passato ad esso.

renderIf(predicate)(element)

renderif.js

'use strict';
const isFunction = input => typeof input === 'function';
export default predicate => elemOrThunk =>
  predicate ? (isFunction(elemOrThunk) ? elemOrThunk() : elemOrThunk) : null;

Clever :) qual è il caso d'uso del thunk?
goldylucks,

Haha. Brillante!
Jaseem Abbas,

Questa soluzione ha senso per i casi d'uso in cui una finestra di dialogo deve essere visualizzata solo quando necessario. Ty!
SoundStage

2
Questo non funzionerà se è necessario mantenere lo stato, rimuovere l'elemento resettare il suo stato. quindi ogni volta che si esegue nuovamente il rendering è come se si crea nuovamente il componente.
Daniel Jose Padilla Peña,

1
devi dare un'occhiata a questo esempio: Nascondi / Mostra componenti in reagisce nativo
sumit kumar pradhan

20

in render () è possibile mostrare in modo condizionale JSX o restituire null come in:

render(){
    return({yourCondition ? <yourComponent /> : null});
}

3
Le parentesi dovrebbero essere richieste nella riga 2.
jiexishede,

Grazie per la soluzione più semplice
Sam

13

Avevo bisogno di passare tra due immagini. Con la commutazione condizionale tra di loro c'era un ritardo di 5 secondi senza immagine visualizzata.

Sto usando l'approccio dalla risposta amos declassata. Pubblicare come nuova risposta perché è difficile inserire un codice nel commento con una formattazione corretta.

Funzione di rendering:

<View style={styles.logoWrapper}>
  <Image
    style={[styles.logo, loading ? styles.hidden : {}]}
    source={require('./logo.png')} />
  <Image
    style={[styles.logo, loading ? {} : styles.hidden]}
    source={require('./logo_spin.gif')} />
</View>

stili:

var styles = StyleSheet.create({
  logo: {
    width: 200,
    height: 200,
  },
  hidden: {
    width: 0,
    height: 0,
  },
});

screencast


Ciò mantiene i componenti in memoria, il che può essere un problema con componenti di grandi dimensioni. Perché non usare i grandi esempi sopra? Inseriranno l'immagine giusta e rimuoveranno completamente l'altra ...
AS

4
nessuno di questi esempi non funziona correttamente quando si tenta di creare un filatore animato. Come ho già detto nella mia risposta su Android che prova a cambiare img per anim gif, causerà un ritardo di 5 secondi quando non viene mostrato nessun png né gif. Credo che il ritardo sia causato dal caricamento di GIF in memoria, che potrebbe richiedere del tempo. Tuttavia iOS sembra fare un lavoro molto migliore qui. Se non mi credi, provalo tu stesso.
mauron85,

1
Naturalmente, come sottolineato, non è la soluzione ottimale per ogni componente. Ma l'IMHO per il caricamento del filatore va bene. Alla fine verrà scaricato quando l'utente passa a un'altra pagina.
mauron85,

13

Il più delle volte sto facendo qualcosa del genere:

class MyComponent extends React.Component {
  constructor(props) {
    super(props);
    this.state = {isHidden: false};
    this.onPress = this.onPress.bind(this);
  }
  onPress() {
    this.setState({isHidden: !this.state.isHidden})
  }
  render() {
    return (
      <View style={styles.myStyle}>

        {this.state.isHidden ? <ToHideAndShowComponent/> : null}

        <Button title={this.state.isHidden ? "SHOW" : "HIDE"} onPress={this.onPress} />
      </View>
    );
  }
}

Se sei un po 'nuovo nella programmazione, questa riga deve essere strana per te:

{this.state.isHidden ? <ToHideAndShowComponent/> : null}

Questa riga equivale a

if (this.state.isHidden)
{
  return ( <ToHideAndShowComponent/> );
}
else
{
  return null;
}

Ma non puoi scrivere una condizione if / else nel contenuto JSX (ad esempio la parte return () di una funzione di rendering) quindi dovrai usare questa notazione.

Questo piccolo trucco può essere molto utile in molti casi e ti suggerisco di usarlo nei tuoi sviluppi perché puoi verificare rapidamente una condizione.

Saluti,


Puoi per favore approfondire come hai definito <ToHideAndShowComponent />
Ritveak

12

inserisci qui la descrizione dell'immagine

Nascondi e mostra la vista principale diActivity Indicator

constructor(props) {
  super(props)

  this.state = {
    isHidden: false
  }  
} 

Nascondi e mostra come follow

{
   this.state.isHidden ?  <View style={style.activityContainer} hide={false}><ActivityIndicator size="small" color="#00ff00" animating={true}/></View> : null
}

Riferimento completo

render() {
    return (
       <View style={style.mainViewStyle}>
          <View style={style.signinStyle}>
           <TextField placeholder='First Name' keyboardType='default' onChangeFirstName={(text) => this.setState({firstName: text.text})}/>
           <TextField placeholder='Last Name' keyboardType='default' onChangeFirstName={(text) => this.setState({lastName: text.text})}/>
           <TextField placeholder='Email' keyboardType='email-address' onChangeFirstName={(text) => this.setState({email: text.text})}/>
           <TextField placeholder='Phone Number' keyboardType='phone-pad' onChangeFirstName={(text) => this.setState({phone: text.text})}/>
           <TextField placeholder='Password' secureTextEntry={true} keyboardType='default' onChangeFirstName={(text) => this.setState({password: text.text})}/>
           <Button  style={AppStyleSheet.buttonStyle} title='Sign up' onPress={() => this.onSignupPress()} color='red' backgroundColor='black'/>
          </View>
          {
            this.state.isHidden ?  <View style={style.activityContainer}><ActivityIndicator size="small" color="#00ff00" animating={true}/></View> : null
          }
      </View>
   );
}

On Il pulsante preme set state come segue

onSignupPress() {
  this.setState({isHidden: true})
}

Quando devi nasconderti

this.setState({isHidden: false})


10

basta usare

style={ width:0, height:0 } // to hide

4
Sarebbe utile se aggiungessi un contesto / dettaglio alla risposta.
UditS,

Supponendo che tu abbia un meccanismo per decidere quale componente nascondere, questa risposta è abbastanza utile. Puoi racchiudere qualsiasi componente che stai cercando di nascondere con una vista con stile = {{larghezza: 0, altezza: 0}}.
Josh Baker,

6
come si ripristina l'elemento alla larghezza e altezza originali?
Qualche Juan,

4
non capisco perché questo sia downvoted, ma in molti casi è un buon consiglio. Devo passare dalla gif animata a quella non animata. La commutazione condizionale img ha causato ritardi senza img sullo schermo. Come parte della correzione, sto visualizzando entrambi img, ma quello che dovrebbe essere nascosto ha larghezza e altezza pari a zero.
mauron85,

Ciò mantiene il componente in memoria, il che può essere un problema con componenti di grandi dimensioni. Perché non usare i grandi esempi sopra? Inseriscono e rimuovono completamente il componente ...
AS

6

Ho avuto lo stesso problema in cui avrei voluto mostrare / nascondere le viste, ma in realtà non volevo che l'interfaccia utente saltasse in giro quando le cose venivano aggiunte / rimosse o necessariamente per gestire il rendering.

Ho scritto un semplice componente per occuparmene. Animato per impostazione predefinita, ma facile da attivare. L'ho messo su GitHub e NPM con un readme, ma tutto il codice è sotto.

npm install --save react-native-hideable-view

import React, { Component, PropTypes } from 'react';
import { Animated  } from 'react-native';

class HideableView extends Component {
  constructor(props) {
    super(props);
    this.state = {
      opacity: new Animated.Value(this.props.visible ? 1 : 0)
    }
  }

  animate(show) {
    const duration = this.props.duration ? parseInt(this.props.duration) : 500;
    Animated.timing(
      this.state.opacity, {
        toValue: show ? 1 : 0,
        duration: !this.props.noAnimation ? duration : 0
      }
    ).start();
  }

  shouldComponentUpdate(nextProps) {
    return this.props.visible !== nextProps.visible;
  }

  componentWillUpdate(nextProps, nextState) {
    if (this.props.visible !== nextProps.visible) {
      this.animate(nextProps.visible);
    }
  }

  render() {
    if (this.props.removeWhenHidden) {
      return (this.visible && this.props.children);
    }
    return (
      <Animated.View style={{opacity: this.state.opacity}}>
        {this.props.children}
      </Animated.View>
    )
  }
}

HideableView.propTypes = {
  visible: PropTypes.bool.isRequired,
  duration: PropTypes.number,
  removeWhenHidden: PropTypes.bool,
  noAnimation: PropTypes.bool
}

export default HideableView;

Bello, proprio quello che stavo cercando :)
Adamski,

Funziona meglio e si comporta come una vista corretta quando si inseriscono altri componenti che hanno un ciclo di vita all'interno della vista (che non funziona visible && (...).
dB.

6

Un'ulteriore opzione è applicare il posizionamento assoluto tramite lo stile , impostando il componente nascosto in coordinate fuori schermo:

<TextInput
    onFocus={this.showCancel()}
    onChangeText={(text) => this.doSearch({input: text})}
    style={this.state.hide ? {position: 'absolute', top: -200} : {}}
/>

A differenza di alcuni dei precedenti suggerimenti, questo nasconderebbe il componente alla vista MA lo renderà (mantenendolo nel DOM), rendendolo così invisibile .


2
Questa idea è adatta a me, grazie. Se qualcuno ha bisogno, guardalo anche tu
Chaki_Black

5
constructor(props) {
    super(props);
    this.state = {
      visible: true,
}
}

dichiarare false false quindi, per impostazione predefinita, modal / view are hide

esempio = () => {

 this.setState({ visible: !this.state.visible })

}

** Chiamata di funzione **

{this.state.visible == false ?
        <View>
            <TouchableOpacity
              onPress= {() => this.example()}>   // call function
                          <Text>
                            show view
                          </Text>
            </TouchableOpacity>

</View>
:
 <View>
    <TouchableOpacity
              onPress= {() => this.example()}>
                          <Text>
                            hide view
                          </Text>
            </TouchableOpacity>
</View> 
 }

3

Se è necessario che il componente rimanga caricato ma nascosto, è possibile impostare l'opacità su 0. (Ne avevo bisogno per la fotocamera expo)

//in constructor    
this.state = {opacity: 100}

/in component
style = {{opacity: this.state.opacity}}

//when you want to hide
this.setState({opacity: 0})


2

Il seguente esempio è la codifica in dattiloscritto con Hooks.

import React, { useState, useEffect } from "react";

........

const App = () => {

   const [showScrollView, setShowScrollView] = useState(false);

   ......

   const onPress = () => {
    // toggle true or false
    setShowScrollView(!showScrollView);
  }

  ......

      </MapboxGL.ShapeSource>
        <View>{showScrollView ? (<DetailsScrollView />) : null}</View>
      </MapboxGL.MapView>
  ......

}

2
// You can use a state to control wether the component is showing or not
const [show, setShow] = useState(false); // By default won't show

// In return(
{
    show && <ComponentName />
}

/* Use this to toggle the state, this could be in a function in the 
main javascript or could be triggered by an onPress */

show == true ? setShow(false) : setShow(true)

// Example:
const triggerComponent = () => {
    show == true ? setShow(false) : setShow(true)
}

// Or
<SomeComponent onPress={() => {show == true ? setShow(false) : setShow(true)}}/>

3
Sebbene questo codice possa risolvere il problema del PO, è meglio includere una spiegazione su come il codice risolve il problema del PO. In questo modo, i futuri visitatori possono imparare dal tuo post e applicarlo al proprio codice. SO non è un servizio di codifica, ma una risorsa per la conoscenza. Inoltre, è più probabile che vengano votate risposte complete e di alta qualità. Queste caratteristiche, insieme alla necessità che tutti i post siano autonomi, sono alcuni dei punti di forza di SO come piattaforma, che lo differenzia dai forum. È possibile modificare per aggiungere ulteriori informazioni e / o integrare le proprie spiegazioni con la documentazione di origine.
YSF

1
Aggiornato, spiegato un po 'di più. Spero che sia d'aiuto!
Oyebola,

0

Molto facile. Basta passare a () => this.showCancel () come di seguito:

<TextInput
        onFocus={() => this.showCancel() }
        onChangeText={(text) => this.doSearch({input: text})} />

<TouchableHighlight 
    onPress={this.hideCancel()}>
    <View>
        <Text style={styles.cancelButtonText}>Cancel</Text>
    </View>
</TouchableHighlight>


0

sto solo usando il metodo seguente per nascondere o visualizzare un pulsante. spero che ti possa aiutare. basta aggiornare lo stato e aggiungere hide css per me

constructor(props) {
   super(props);
      this.state = {
      visibleStatus: false
   };
}
updateStatusOfVisibility () {
   this.setStatus({
      visibleStatus: true
   });
}
hideCancel() {
   this.setStatus({visibleStatus: false});
}

render(){
   return(
    <View>
        <TextInput
            onFocus={this.showCancel()}
            onChangeText={(text) => {this.doSearch({input: text}); this.updateStatusOfVisibility()}} />

         <TouchableHighlight style={this.state.visibleStatus ? null : { display: "none" }}
             onPress={this.hideCancel()}>
            <View>
                <Text style={styles.cancelButtonText}>Cancel</Text>
            </View>
        </TouchableHighlight>
     </View>)
}

0

In realtà, nello sviluppo di iOS da react-nativequando uso display: 'none'o qualcosa di simile di seguito:

const styles = StyleSheet.create({
  disappearImage: {
    width: 0,
    height: 0
  }
});

L'iOS non carica nient'altro del componente Image come onLoado ecc, quindi ho deciso di utilizzare qualcosa come di seguito:

const styles = StyleSheet.create({
  disappearImage: {
    width: 1,
    height: 1,
    position: 'absolute',
    top: -9000,
    opacity: 0
  }
});

0

L'unico modo per mostrare o nascondere un componente in reattivo nativo è verificare un valore di un parametro di stato app come stateo props. Ho fornito un esempio completo come di seguito:

import React, {Component} from 'react';
import {View,Text,TextInput,TouchableHighlight} from 'react-native'

class App extends Component {

    constructor(props){
        super(props);
        this.state={
            show:false
        }
}

    showCancel=()=>{
        this.setState({show:true})
    };

    hideCancel=()=>{
        this.setState({show:false})
    };

    renderTouchableHighlight(){
        if(this.state.show){
           return(
               <TouchableHighlight
                   style={{borderColor:'black',borderWidth:1,marginTop:20}}
                   onPress={this.hideCancel}>
                   <View>
                       <Text>Cancel</Text>
                   </View>
               </TouchableHighlight>
           )
        }
        return null;
    }

    render() {


        return (
            <View style={{justifyContent:'center',alignItems:'center',flex:1}}>
                <TextInput
                    style={{borderColor:'black',borderBottomWidth:1}}
                    onFocus={this.showCancel}
                />
                {this.renderTouchableHighlight()}

            </View>
        );
    }
}

export default App;

Ecco il risultato


0

Se vuoi nasconderlo ma mantenere lo spazio occupato dal componente come l' visibility: hiddenimpostazione css nello stile del componente opacity: 0dovrebbe fare il trucco.

A seconda del componente potrebbero essere necessari altri passaggi per disabilitare la funzionalità poiché è possibile l'interazione con un elemento invisibile.


0

È possibile utilizzare le condizioni per mostrare e nascondere i componenti

constructor(){

    super();

    this.state ={

      isVisible:true

    }
  }

  ToggleFunction = () => {

    this.setState(state => ({

      isVisible: !state.isVisible

    }));

  };

  render() {
  
    return (

      <View style={styles.MainContainer}>

      {

        this.state.isVisible ? <Text style= {{ fontSize: 20, color: "red", textAlign: 'center' }}> Hello World! </Text> : null
      }

      <Button title="Toggle Visibility" onPress={this.ToggleFunction} />

      </View>
    );
  }

-2
checkincheckout = () => {
        this.setState({ visible: !this.state.visible })
}

render() {
        return (
{this.state.visible == false ?
        <View style={{ alignItems: 'center', flexDirection: 'row', marginTop: 50 }}>

        <View style={{ flex: 1, alignItems: 'center', flexDirection: 'column' }}>

            <TouchableOpacity onPress={() => this.checkincheckout()}>

                <Text style={{ color: 'white' }}>Click to Check in</Text>

            </TouchableOpacity>

        </View>

    </View>
:
<View style={{ alignItems: 'center', flexDirection: 'row', marginTop: 50 }}>

<View style={{ flex: 1, alignItems: 'center', flexDirection: 'column' }}>

   <TouchableOpacity onPress={() => this.checkincheckout()}>

        <Text style={{ color: 'white' }}>Click to Check out</Text>

    </TouchableOpacity>

</View>

</View>
 }

);
}

È tutto. goditi il ​​tuo codice ...

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.