Masquer / afficher les composants dans React Native


143

Je suis vraiment nouveau sur React Native et je me demande comment puis-je masquer / afficher un composant.
Voici mon cas de test:

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

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

J'ai un TextInputcomposant, ce que je veux, c'est afficher le TouchableHighlightmoment où l'entrée obtient le focus, puis le masquer TouchableHighlightlorsque l'utilisateur appuie sur le bouton d'annulation.

Je ne sais pas comment "accéder" au TouchableHighlightcomposant pour le cacher / le montrer dans mes fonctions showCancel/hideCancel.
Aussi, comment puis-je masquer le bouton dès le début?


vous devez consulter cet exemple: Masquer / Afficher les composants dans
react

Réponses:


135

Je ferais quelque chose comme ça:

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
Merci beaucoup pour cela, juste un petit changement que je devais faire: onFocus = {() => this.showCancel ()} cela doit être une fonction de rappel.
Crysfel

3
Seulement travaillé pour moi après avoir changé le return ''enreturn null
k7k0

33
Vous pouvez également le faire {someBoolVal && <Component />}et cela ne montrera que si la valeur booléenne est vraie.
Nathan Hyland

C'est la meilleure réponse
Kirill Gusyatin

3
Je ne sais pas que c'est la réponse acceptée qui n'implémente pas la fonctionnalité originale souhaitée afficher / masquer, mais plutôt ajouter / supprimer
Muhammad Aref

150

Dans votre fonction de rendu:

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

Alors faites simplement:

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

2
Cela a fonctionné pour moi. Cependant, je ne suis pas sûr de savoir pourquoi, lorsque je fais quelque chose comme { this.state.showTheThing && (<Text>foo</Text> && <Text>bar</Text>)}seule "barre" est affichée dans l'interface utilisateur. Je m'attendrais à ce que "foo" et "bar" soient affichés. Ce que j'ai besoin de faire pour résoudre ce problème, c'est d'appeler{ this.state.showTheThing && (<Text>foo</Text>} { this.state.showTheThing && (<Text>bar</Text>}
tonatiuhnb

2
peut-être que cela fonctionne? parce que la logique &&ne combine pas les éléments{ this.state.showTheThing && (<View><Text>foo</Text><Text>bar</Text></View>)}
muescha

Cela a fonctionné pour moi, je voulais afficher un bouton "Étape suivante" lorsqu'un utilisateur a téléchargé sa photo de profil. donc mon code était:{this.state.hasPic && <Button title="Go to next step" onPress={this._nextStep} />}
Daggie Blanqx - Douglas Mwangi

Si vous avez du mal à afficher plusieurs composants, enveloppez votre composant avec un fragment. par exemple. <React.Fragment><Text>Foo</Text><Text>Bar></Text></React.Fragment>
Ben Cull

48

En réaction ou en réaction native, la façon dont le composant cacher / afficher ou ajouter / supprimer ne fonctionne pas comme dans Android ou iOS. La plupart d'entre nous pensent qu'il y aurait une stratégie similaire comme

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

Mais la façon dont réagissent le travail natif est complètement différente. Le seul moyen d'obtenir ce type de fonctionnalité est d'inclure votre composant dans votre DOM ou de le supprimer du DOM.

Ici, dans cet exemple, je vais définir la visibilité de la vue du texte en fonction du clic sur le bouton.

entrez la description de l'image ici

L'idée derrière cette tâche est de créer une variable d'état appelée état dont la valeur initiale est définie sur false lorsque l'événement de clic sur le bouton se produit, puis sa valeur bascule. Nous allons maintenant utiliser cette variable d'état lors de la création du composant.

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

la seule chose à remarquer dans cet extrait de code est de savoir renderIfqui est en fait une fonction qui retournera le composant qui lui est passé en fonction de la valeur booléenne qui lui est passée.

renderIf(predicate)(element)

renderif.js

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

Clever :) quel est le cas d'utilisation du thunk?
goldylucks

Haha. Brillant!
Jaseem Abbas

Cette solution est judicieuse pour les cas d'utilisation où une boîte de dialogue doit être rendue uniquement lorsque cela est nécessaire. Ty!
SoundStage

2
Cela ne fonctionnera pas si vous devez conserver l'état, supprimer l'élément réinitialiser son état. Ainsi, chaque fois que vous effectuez un nouveau rendu, vous créez à nouveau un composant.
Daniel Jose Padilla Peña

1
vous devez consulter cet exemple: Masquer / Afficher les composants dans
react

20

dans render (), vous pouvez afficher conditionnellement le JSX ou retourner null comme dans:

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

3
Les parenthèses doivent être obligatoires dans la ligne 2.
jiexishede

Merci pour la solution la plus simple
Sam

13

J'avais besoin de basculer entre deux images. Avec la commutation conditionnelle entre eux, il y avait un délai de 5 secondes sans image affichée.

J'utilise l'approche de la réponse amos votée à la baisse. Publier comme nouvelle réponse car il est difficile de mettre du code en commentaire avec un formatage approprié.

Fonction de rendu:

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

Modes:

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

screencast


Cela garde les composants en mémoire, ce qui peut être un problème avec les gros composants. Pourquoi ne pas utiliser les excellents exemples ci-dessus? Ils inséreront la bonne image et enlèveront l'autre complètement ...
COMME

4
aucun de ces exemples ne fonctionne correctement lorsque vous essayez de créer un spinner animé. Comme je l'ai déjà mentionné dans ma réponse sur Android, essayer de changer img pour anim gif entraînera un retard de 5 s lorsque aucun png ni gif n'est affiché. Je pense que le retard est causé par le chargement de gif en mémoire, ce qui peut prendre un certain temps. Cependant, iOS semble faire un bien meilleur travail ici. Si vous ne me croyez pas, essayez-le vous-même.
mauron85

1
Bien sûr, comme indiqué, ce n'est pas la solution optimale pour chaque composant. Mais à mon humble avis pour le chargement de spinner c'est très bien. Il sera finalement déchargé lorsque l'utilisateur passe à une autre page.
mauron85

13

La plupart du temps, je fais quelque chose comme ceci:

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

Si vous êtes un peu novice en programmation, cette ligne doit vous être étrange:

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

Cette ligne équivaut à

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

Mais vous ne pouvez pas écrire une condition if / else dans le contenu JSX (par exemple la partie return () d'une fonction de rendu), vous devrez donc utiliser cette notation.

Cette petite astuce peut être très utile dans de nombreux cas et je vous suggère de l'utiliser dans vos développements car vous pouvez vérifier rapidement une condition.

Cordialement,


Pouvez-vous s'il vous plaît expliquer comment vous avez défini <ToHideAndShowComponent />
Ritveak

12

entrez la description de l'image ici

Masquer et afficher la vue parent deActivity Indicator

constructor(props) {
  super(props)

  this.state = {
    isHidden: false
  }  
} 

Masquer et afficher comme suit

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

Référence complète

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

Les pressions sur le bouton définissent l'état comme suit

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

Quand tu as besoin de te cacher

this.setState({isHidden: false})


10

juste utiliser

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

4
Il serait utile que vous ajoutiez du contexte / des détails à la réponse.
UditS

En supposant que vous disposez d'un mécanisme pour décider quel composant cacher, cette réponse est très utile. Vous pouvez envelopper n'importe quel composant que vous essayez de masquer avec une vue avec style = {{width: 0, height: 0}}.
Josh Baker

6
comment restaurer l'élément à sa largeur et à sa hauteur d'origine?
Some Juan le

4
Je ne comprends pas pourquoi ce vote est défavorable, mais dans de nombreux cas, c'est un bon conseil. J'ai besoin de basculer entre gif animé et non animé. La commutation conditionnelle img a provoqué des retards sans img à l'écran. Dans le cadre de la correction, j'affiche les deux img, mais celui qui devrait être caché a une largeur et une hauteur nulles.
mauron85

Cela garde le composant en mémoire, ce qui peut être un problème avec les gros composants. Pourquoi ne pas utiliser les excellents exemples ci-dessus? Ils insèrent et retirent complètement le composant ...
AS

6

J'ai eu le même problème où je voudrais afficher / masquer les vues, mais je ne voulais vraiment pas que l'interface utilisateur saute lorsque des éléments ont été ajoutés / supprimés ou nécessairement pour traiter le re-rendu.

J'ai écrit un composant simple pour m'en occuper pour moi. Animé par défaut, mais facile à basculer. Je l'ai mis sur GitHub et NPM avec un readme, mais tout le code est ci-dessous.

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;

Belle, juste ce que je cherchais :)
Adamski

Cela fonctionne mieux et se comporte comme une vue correcte lorsque vous placez d'autres composants qui ont un cycle de vie à l'intérieur de la vue (ce qui ne fonctionne pas avec visible && (...).
dB.

6

Une option supplémentaire consiste à appliquer un positionnement absolu via le style , en définissant le composant masqué en coordonnées hors écran:

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

Contrairement à certaines des suggestions précédentes, cela masquerait votre composant de la vue MAIS le rendra également (le conservera dans le DOM), le rendant ainsi vraiment invisible .


2
Cette idée me convient, merci. Si quelqu'un a besoin, regardez-le aussi: gist.github.com/jaysoo/cbb81a07cc22015a72e9
Chaki_Black

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

déclarer visible false donc par défaut modal / view sont hide

exemple = () => {

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

}

** Appel de fonction **

{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

Si vous avez besoin que le composant reste chargé mais masqué, vous pouvez définir l'opacité sur 0. (J'en avais besoin pour la caméra expo par exemple)

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

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

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


2

L'exemple suivant est le codage en typographie avec 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
Bien que ce code puisse résoudre le problème du PO, il est préférable d'inclure une explication sur la façon dont votre code résout le problème du PO. De cette manière, les futurs visiteurs peuvent apprendre de votre publication et l'appliquer à leur propre code. SO n'est pas un service de codage, mais une ressource de connaissances. De plus, les réponses complètes et de haute qualité sont plus susceptibles d'être votées. Ces fonctionnalités, ainsi que l'exigence que tous les messages soient autonomes, sont quelques-unes des forces de SO en tant que plate-forme, qui le différencie des forums. Vous pouvez modifier pour ajouter des informations supplémentaires et / ou pour compléter vos explications avec la documentation source.
ysf

1
Mis à jour, expliqué un peu plus. J'espère que ça aide!
Oyebola le

0

Très facile. Changez simplement en () => this.showCancel () comme ci-dessous:

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

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

vous devez consulter cet exemple: Masquer / Afficher les composants dans
react

0

J'utilise juste la méthode ci-dessous pour masquer ou afficher un bouton. j'espère que cela vous aidera. il me suffit de mettre à jour le statut et d'ajouter hide css

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

En fait, dans le développement iOS react-nativelorsque j'utilise display: 'none'ou quelque chose comme ci-dessous:

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

L'iOS ne charge rien d'autre du composant Image comme onLoadou etc., j'ai donc décidé d'utiliser quelque chose comme ci-dessous:

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

0

La seule façon d'afficher ou de masquer un composant dans react native est de vérifier la valeur d'un paramètre d'état d'application comme stateou props. J'ai fourni un exemple complet comme ci-dessous:

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;

Voici le résultat


0

Si vous souhaitez le masquer tout en gardant l'espace occupé par le composant comme le visibility: hiddenparamètre css dans le style du composantopacity: 0 devrait faire l'affaire.

En fonction du composant, d'autres étapes de désactivation de la fonctionnalité peuvent être nécessaires car une interaction avec un élément invisible est possible.


0

Vous pouvez utiliser les conditions pour afficher et masquer les composants

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

);
}

c'est tout. profitez de votre codage ...

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.