Ocultar / Mostrar componentes en reaccionar nativo


143

Soy realmente nuevo en React Native y me pregunto cómo puedo ocultar / mostrar un componente.
Aquí está mi caso de prueba:

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

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

tengo un TextInput componente, lo que quiero es mostrar TouchableHighlightcuándo la entrada obtiene el foco, luego ocultar TouchableHighlightcuando el usuario presiona el botón cancelar.

No sé cómo "acceder" al TouchableHighlightcomponente para ocultarlo / mostrarlo dentro de mis funciones showCancel/hideCancel.
Además, ¿cómo puedo ocultar el botón desde el principio?


Respuestas:


135

Haría algo como esto:

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
Muchas gracias por esto, solo un pequeño cambio que tuve que hacer: onFocus = {() => this.showCancel ()} esto debe ser una función de devolución de llamada.
Crysfel

3
Solo funcionó para mí después de cambiar el return ''areturn null
k7k0

33
También puede hacerlo {someBoolVal && <Component />}y solo se mostrará si el valor bool es verdadero.
Nathan Hyland

Esta es la mejor respuesta
Kirill Gusyatin

3
No sé, esta es la respuesta aceptada que no implementa la funcionalidad deseada original mostrar / ocultar, sino agregar / eliminar
Muhammad Aref

150

En su función de renderizado:

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

Entonces solo haz:

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

2
Esto funcionó para mí. Sin embargo, no estoy seguro de por qué cuando hago algo como { this.state.showTheThing && (<Text>foo</Text> && <Text>bar</Text>)}solo se muestra "barra" en la interfaz de usuario. Esperaría que se mostraran "foo" y "bar". Lo que necesito hacer para resolver esto es llamar{ this.state.showTheThing && (<Text>foo</Text>} { this.state.showTheThing && (<Text>bar</Text>}
tonatiuhnb

2
tal vez esto funciona? porque lo lógico &&no combina elementos{ this.state.showTheThing && (<View><Text>foo</Text><Text>bar</Text></View>)}
muescha

Esto funcionó para mí, quería mostrar un botón de "Siguiente paso" cuando un usuario subió su foto de perfil. entonces mi código era:{this.state.hasPic && <Button title="Go to next step" onPress={this._nextStep} />}
Daggie Blanqx - Douglas Mwangi

Para cualquiera que tenga dificultades para mostrar más de un componente, envuelva su componente con un fragmento. p.ej. <React.Fragment><Text>Foo</Text><Text>Bar></Text></React.Fragment>
Ben Cull

48

En reaccionar o reaccionar de forma nativa, la forma en que el componente ocultar / mostrar o agregar / eliminar no funciona como en Android o iOS. La mayoría de nosotros cree que habría una estrategia similar como

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

Pero la forma en que reacciona el trabajo nativo es completamente diferente. La única forma de lograr este tipo de funcionalidad es incluir su componente en su DOM o eliminarlo de DOM.

Aquí, en este ejemplo, voy a establecer la visibilidad de la vista de texto en función del clic del botón.

ingrese la descripción de la imagen aquí

La idea detrás de esta tarea es crear una variable de estado llamada estado que tenga el valor inicial establecido en falso cuando se produce el evento de clic del botón y luego el valor cambia. Ahora usaremos esta variable de estado durante la creación 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>
    );
  }
}

Lo único que se debe notar en este fragmento es renderIfcuál es en realidad una función que devolverá el componente que se le pasó en función del valor booleano que se le pasó.

renderIf(predicate)(element)

renderif.js

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

Clever :) ¿Cuál es el caso de uso del thunk?
goldylucks

Jaja. ¡Brillante!
Jaseem Abbas

Esta solución tiene sentido para casos de uso en los que un cuadro de diálogo solo debe representarse cuando sea necesario. Ty!
SoundStage

2
Esto no funcionará si necesita mantener el estado, eliminar elemento restablecer su estado. así que cada vez que vuelve a renderizar es como si volviera a crear el componente.
Daniel Jose Padilla Peña


20

en render () puede mostrar condicionalmente el JSX o devolver nulo como en:

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

3
Los paréntesis deben ser obligatorios en la línea 2.
jiexishede

Gracias por la solución más simple
Sam

13

Necesitaba cambiar entre dos imágenes. Con el cambio condicional entre ellos hubo un retraso de 5 segundos sin mostrar ninguna imagen.

Estoy usando el enfoque de la respuesta amos con voto negativo. Publicar como nueva respuesta porque es difícil poner código en el comentario con el formato adecuado.

Función de procesamiento:

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

Estilos:

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

screencast


Esto mantiene los componentes en la memoria, lo que puede ser un problema con componentes grandes. ¿Por qué no usar los excelentes ejemplos anteriores? Insertarán la imagen correcta y eliminarán la otra completamente ...
COMO el

44
ninguno de esos ejemplos no funciona correctamente cuando intentas crear un spinner animado. Como ya mencioné en mi respuesta en Android, tratar de cambiar img por anim gif, causará un retraso de 5 segundos cuando no se muestre png ni gif. Creo que la demora es causada por cargar gif en la memoria, lo que puede llevar algún tiempo. Sin embargo, iOS parece hacer un trabajo mucho mejor aquí. Si no me crees, pruébalo tú mismo.
mauron85

1
Por supuesto, como se señaló, no es la solución óptima para cada componente. Pero en mi humilde opinión para cargar spinner está bien. Eventualmente se descargará cuando el usuario haga la transición a otra página.
mauron85

13

La mayoría de las veces estoy haciendo algo como esto:

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 eres nuevo en la programación, esta línea debe ser extraña para ti:

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

Esta línea es equivalente a

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

Pero no puede escribir una condición if / else en el contenido JSX (por ejemplo, la parte return () de una función de representación), por lo que tendrá que usar esta notación.

Este pequeño truco puede ser muy útil en muchos casos y le sugiero que lo use en sus desarrollos porque puede verificar rápidamente una condición.

Saludos,


¿Puede explicar cómo definió <ToHideAndShowComponent />
Ritveak

12

ingrese la descripción de la imagen aquí

Ocultar y mostrar vista principal deActivity Indicator

constructor(props) {
  super(props)

  this.state = {
    isHidden: false
  }  
} 

Ocultar y mostrar como sigue

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

Referencia completa

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

El botón On presiona establecer el estado de la siguiente manera

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

Cuando necesitas esconderte

this.setState({isHidden: false})


10

Solo usa

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

44
Sería útil si agrega algún contexto / detalle a la respuesta.
UditS

Suponiendo que tiene un mecanismo para decidir qué componente ocultar, esta respuesta es bastante útil. Puede ajustar cualquier componente que esté tratando de ocultar con una Vista con estilo = {{ancho: 0, altura: 0}}.
Josh Baker,

66
¿Cómo restaura el elemento al ancho y alto originales?
Algunos Juan

44
No entiendo por qué se rechaza esto, pero en muchos casos es un buen consejo. Necesito cambiar entre gifs animados y no animados. El cambio de imagen condicional causó demoras sin imagen en la pantalla. Como parte de la solución, estoy mostrando ambos img, pero el que debería estar oculto tiene cero ancho y alto.
mauron85

Esto mantiene el componente en memoria, lo que puede ser un problema con componentes grandes. ¿Por qué no usar los excelentes ejemplos anteriores? Insertan y eliminan componentes por completo ...
COMO

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

declarar visible falso, por lo que, por defecto, modal / view se ocultan

ejemplo = () => {

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

}

**Llamada de función **

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

6

Tuve el mismo problema en el que me gustaría mostrar / ocultar vistas, pero realmente no quería que la interfaz de usuario saltara cuando se agregaran / eliminaran cosas o que necesariamente se ocupara de volver a renderizar.

Escribí un componente simple para tratarlo por mí. Animado por defecto, pero fácil de alternar. Lo puse en GitHub y NPM con un archivo Léame, pero todo el código está debajo.

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;

Bonito, justo lo que estaba buscando :)
Adamski

Esto funciona mejor y se comporta como una vista adecuada cuando coloca otros componentes que tienen un ciclo de vida dentro de la vista (que no funciona con visible && (...).
dB.

6

Una opción adicional es aplicar el posicionamiento absoluto a través del estilo , configurando el componente oculto en coordenadas fuera de la pantalla:

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

A diferencia de algunas de las sugerencias anteriores, esto ocultaría su componente de la vista, PERO también lo representará (lo mantendrá en el DOM), lo que lo hará realmente invisible .


2
Esta idea me conviene, gracias. Si alguien lo necesita, mírelo también: gist.github.com/jaysoo/cbb81a07cc22015a72e9
Chaki_Black

3

Si necesita que el componente permanezca cargado pero oculto, puede establecer la opacidad en 0. (necesitaba esto para la cámara de exposición, por ejemplo)

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

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

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


2

El siguiente ejemplo es la codificación en mecanografiado 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
Si bien este código puede resolver el problema del OP, es mejor incluir una explicación sobre cómo su código aborda el problema del OP. De esta forma, los futuros visitantes pueden aprender de su publicación y aplicarla a su propio código. SO no es un servicio de codificación, sino un recurso para el conocimiento. Además, es más probable que se voten las respuestas completas de alta calidad. Estas características, junto con el requisito de que todas las publicaciones sean independientes, son algunos de los puntos fuertes de SO como plataforma, que lo diferencia de los foros. Puede editar para agregar información adicional y / o complementar sus explicaciones con la documentación de origen.
ysf

1
Actualizado, explicado un poco más. ¡Espero eso ayude!
Oyebola

0

Muy fácil. Simplemente cambie a () => this.showCancel () como a continuación:

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

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


0

Solo estoy usando el siguiente método para ocultar o ver un botón. Espero que te ayude. solo actualizar el estado y agregar hide css es suficiente para mí

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 realidad, en el desarrollo de iOS react-nativecuando uso display: 'none'o algo como a continuación:

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

El iOS no carga nada más del componente de imagen como onLoado etc., así que decidí usar algo como a continuación:

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

0

La única forma de mostrar u ocultar un componente en react native es comprobando un valor de un parámetro del estado de la aplicación como stateo props. Proporcioné un ejemplo completo de la siguiente manera:

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;

Aquí está el resultado.


0

Si desea ocultarlo pero mantener el espacio ocupado por el componente como la visibility: hiddenconfiguración de css en el estilo del componente opacity: 0debería ser el truco.

Dependiendo del componente, pueden ser necesarios otros pasos para deshabilitar la funcionalidad, ya que es posible la interacción con un elemento invisible.


0

Puede usar las condiciones para mostrar y ocultar los componentes

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

);
}

eso es todo. disfruta tu codificación ...

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.