Ukryj / pokaż komponenty w reagowaniu natywnym

143

Jestem naprawdę nowy w React Native i zastanawiam się, jak mogę ukryć / pokazać komponent.
Oto mój przypadek testowy:

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

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

Mam TextInputkomponent, chcę pokazać, TouchableHighlightkiedy dane wejściowe otrzymają fokus, a następnie ukryć, TouchableHighlightkiedy użytkownik naciśnie przycisk Anuluj.

Nie wiem, jak uzyskać dostęp do TouchableHighlightkomponentu, aby ukryć / pokazać go w moich funkcjach showCancel/hideCancel.
Jak mogę ukryć przycisk od samego początku?

Crysfel
źródło
musisz sprawdzić ten przykład: Ukryj / pokaż komponenty w
React

Odpowiedzi:

135

Zrobiłbym coś takiego:

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

});
Mayank Patel
źródło
1
Dziękuję bardzo za to, tylko jedna mała zmiana, którą musiałem zrobić: onFocus = {() => this.showCancel ()} to musi być funkcja zwrotna.
Crysfel
3
Pracował tylko dla mnie po zmianie return ''nareturn null
k7k0
33
Możesz także to zrobić, {someBoolVal && <Component />}a pokaże się tylko wtedy, gdy wartość bool jest prawdziwa.
Nathan Hyland,
To najlepsza odpowiedź
Kirill Gusyatin
3
Nie wiem, że jest to akceptowana odpowiedź, która nie implementuje oryginalnych pożądanych funkcji pokaż / ukryj, ale zamiast tego dodaj / usuń
Muhammad Aref
150

W swojej funkcji renderującej:

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

Następnie po prostu wykonaj:

this.setState({showTheThing: true})  // to show it  
this.setState({showTheThing: false}) // to hide it
Krishan Gupta
źródło
2
To zadziałało dla mnie. Jednak nie jestem pewien, dlaczego kiedy robię coś takiego, jak { this.state.showTheThing && (<Text>foo</Text> && <Text>bar</Text>)}tylko „pasek” jest wyświetlany w interfejsie użytkownika. Spodziewałbym się, że wyświetlą się „foo” i „bar”. To, co musiałem zrobić, aby to rozwiązać, to zadzwonić{ this.state.showTheThing && (<Text>foo</Text>} { this.state.showTheThing && (<Text>bar</Text>}
tonatiuhnb
2
może to działa? bo logiczne &&nie łączy elementów{ this.state.showTheThing && (<View><Text>foo</Text><Text>bar</Text></View>)}
muescha
To zadziałało dla mnie, chciałem pokazać przycisk „Następny krok”, gdy użytkownik załaduje swój profilepicure. więc mój kod brzmiał:{this.state.hasPic && <Button title="Go to next step" onPress={this._nextStep} />}
Daggie Blanqx - Douglas Mwangi
Każdy, kto boryka się z wyświetlaniem więcej niż jednego komponentu, powinien otoczyć komponent fragmentem. na przykład. <React.Fragment><Text>Foo</Text><Text>Bar></Text></React.Fragment>
Ben Cull,
48

Reagując lub reaguj natywnie, sposób, w jaki komponent ukryj / pokaż lub dodaj / usuń nie działa jak w systemie Android lub iOS. Większość z nas uważa, że ​​byłaby podobna strategia

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

Ale sposób, w jaki reagują na rodzime prace, jest zupełnie inny. Jedynym sposobem osiągnięcia tego rodzaju funkcjonalności jest włączenie komponentu do DOM lub usunięcie z DOM.

W tym przykładzie ustawię widoczność widoku tekstu na podstawie kliknięcia przycisku.

wprowadź opis obrazu tutaj

Ideą tego zadania jest utworzenie zmiennej stanu o nazwie stan, której wartość początkowa jest ustawiona na fałsz, gdy nastąpi zdarzenie kliknięcia przycisku, a następnie zostanie przełączona. Teraz użyjemy tej zmiennej stanu podczas tworzenia komponentu.

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

jedyną rzeczą, na którą należy zwrócić uwagę w tym fragmencie, jest fakt, że jest renderIfto funkcja, która zwróci przekazany jej komponent na podstawie przekazanej wartości logicznej.

renderIf(predicate)(element)

renderif.js

'use strict';
const isFunction = input => typeof input === 'function';
export default predicate => elemOrThunk =>
  predicate ? (isFunction(elemOrThunk) ? elemOrThunk() : elemOrThunk) : null;
Rajan Twanabashu
źródło
Sprytne :) Jaki jest przypadek użycia thunk?
goldylucks
Ha ha. Znakomity!
Jaseem Abbas
To rozwiązanie ma sens w przypadkach użycia, w których okno dialogowe musi być renderowane tylko w razie potrzeby. Ty!
SoundStage
2
To nie zadziała, jeśli chcesz zachować status, usunąć element, zresetować jego stan. więc za każdym razem, gdy renderujesz ponownie, przypomina to tworzenie komponentu od nowa.
Daniel Jose Padilla Peña
1
musisz sprawdzić ten przykład: Ukryj / pokaż komponenty w
React
20

w render () możesz warunkowo pokazać JSX lub zwrócić wartość null jak w:

render(){
    return({yourCondition ? <yourComponent /> : null});
}
Zniszczyć
źródło
3
Nawiasy powinny być wymagane w linii 2.
jiexishede
Dziękuję za najprostsze rozwiązanie
Sam
13

Musiałem przełączać się między dwoma obrazami. Przy warunkowym przełączaniu między nimi następowało 5-sekundowe opóźnienie bez wyświetlania obrazu.

Używam podejścia z obniżonej odpowiedzi amos. Publikowanie jako nowa odpowiedź, ponieważ trudno jest umieścić kod w komentarzu przy odpowiednim formatowaniu.

Funkcja renderowania:

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

Style:

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

screencast

mauron85
źródło
Dzięki temu komponenty pozostają w pamięci, co może być problemem w przypadku dużych komponentów. Dlaczego nie skorzystać z powyższych wspaniałych przykładów? Wstawią właściwy obraz, a drugi całkowicie usuną ...
JAKO
4
żaden z tych przykładów nie działa poprawnie, gdy próbujesz utworzyć animowany spinner. Jak już wspomniałem w mojej odpowiedzi na Androida, próba przełączenia img na anim gif spowoduje opóźnienie 5s, gdy nie jest wyświetlany żaden png ani gif. Uważam, że opóźnienie jest spowodowane ładowaniem gif do pamięci, co może zająć trochę czasu. Jednak iOS wydaje się tutaj radzić sobie znacznie lepiej. Jeśli mi nie wierzysz, spróbuj sam.
mauron85
1
Oczywiście, jak wskazano, nie jest to optymalne rozwiązanie dla każdego elementu. Ale IMHO do ładowania spinnera jest w porządku. W końcu zostanie rozładowany, gdy użytkownik przejdzie na inną stronę.
mauron85
13

Przez większość czasu robię coś takiego:

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

Jeśli programowanie jest dla Ciebie nowością, ta linia musi być dla Ciebie dziwna:

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

Ta linia jest odpowiednikiem

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

Ale nie możesz napisać warunku if / else w treści JSX (np. Część return () funkcji renderującej), więc będziesz musiał użyć tej notacji.

Ta mała sztuczka może być bardzo przydatna w wielu przypadkach i sugeruję użycie jej w twoich opracowaniach, ponieważ możesz szybko sprawdzić stan.

Pozdrowienia,

KuroAku
źródło
Czy możesz wyjaśnić, jak zdefiniowałeś <ToHideAndShowComponent />
Ritveak,
12

wprowadź opis obrazu tutaj

Ukryj i pokaż widok rodzicaActivity Indicator

constructor(props) {
  super(props)

  this.state = {
    isHidden: false
  }  
} 

Ukryj i pokaż jako obserwuj

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

Pełne odniesienie

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

Przycisk włączania ustawia stan w następujący sposób

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

Kiedy musisz się ukryć

this.setState({isHidden: false})
Surowa Valanda
źródło
10

po prostu użyj

style={ width:0, height:0 } // to hide
amos
źródło
4
Byłoby pomocne, gdybyś dodał do odpowiedzi kontekst / szczegół.
UditS
Zakładając, że masz mechanizm decydujący o tym, który komponent ukryć, ta odpowiedź jest całkiem przydatna. Możesz zawinąć dowolny komponent, który próbujesz ukryć, widokiem o stylu = {{szerokość: 0, wysokość: 0}}.
Josh Baker
6
jak przywrócić element do oryginalnej szerokości i wysokości?
Jakiś Juan,
4
nie rozumiem, dlaczego jest to odrzucane, ale w wielu przypadkach jest to dobra rada. Muszę przełączać się między animowanym i nieanimowanym gifem. Warunkowe przełączanie img powodowało opóźnienia bez wyświetlania obrazu na ekranie. W ramach poprawki wyświetlam oba obrazy, ale ten, który powinien być ukryty, ma zerową szerokość i wysokość.
mauron85,
Dzięki temu komponent pozostaje w pamięci, co może być problemem w przypadku dużych komponentów. Dlaczego nie skorzystać z powyższych wspaniałych przykładów? Wkładają i całkowicie usuwają komponent ...
AS
6

Miałem ten sam problem, w którym chciałbym pokazać / ukryć widoki, ale naprawdę nie chciałem, aby interfejs użytkownika skakał po dodaniu / usunięciu rzeczy lub koniecznie zajmował się ponownym renderowaniem.

Napisałem prosty komponent, aby sobie z tym poradzić. Animowany domyślnie, ale łatwy do przełączenia. Umieściłem to na GitHubie i NPM z plikiem readme, ale cały kod jest poniżej.

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;
Tonithy
źródło
Fajny, właśnie to, czego szukałem :)
Adamski
To działa najlepiej i zachowuje się jak właściwy widok, gdy umieścisz w widoku inne komponenty, które mają cykl życia (co nie działa z visible && (...).
dB.
6

Dodatkową opcją jest zastosowanie pozycjonowania bezwzględnego poprzez stylizację , ustawiając ukryty komponent we współrzędnych poza ekranem:

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

W przeciwieństwie do niektórych poprzednich sugestii, spowoduje to ukrycie komponentu przed widokiem, ALE również go wyrenderuje (zachowa w DOM), czyniąc go naprawdę niewidocznym .

d4vidi
źródło
2
Ten pomysł mi odpowiada, dzięki. Jeśli ktoś potrzebuje, spójrz też na to: gist.github.com/jaysoo/cbb81a07cc22015a72e9
Chaki_Black
5
constructor(props) {
    super(props);
    this.state = {
      visible: true,
}
}

Deklaruj widoczne fałsz, więc domyślnie modalne / widok są ukryte

example = () => {

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

}

** Wywołanie funkcji **

{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> 
 }
Shivo'ham 0
źródło
3

Jeśli chcesz, aby komponent pozostał załadowany, ale ukryty, możesz ustawić krycie na 0. (potrzebowałem tego na przykład dla kamery expo)

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

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

//when you want to hide
this.setState({opacity: 0})
ykay, mówi Przywróć Monikę
źródło
2

Możesz użyć mojego modułu react-native-display, aby pokazać / ukryć komponenty.

Danny Michaeli
źródło
2

Poniższy przykład to kodowanie w maszynie z hookami.

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

}
madeinQuant
źródło
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)}}/>
Oyebola
źródło
3
Chociaż ten kod może rozwiązać problem PO, najlepiej jest dołączyć wyjaśnienie, w jaki sposób Twój kod rozwiązuje problem PO. W ten sposób przyszli odwiedzający mogą uczyć się z Twojego postu i zastosować go do własnego kodu. SO nie jest usługą programistyczną, ale źródłem wiedzy. Również wysokiej jakości, kompletne odpowiedzi mają większe szanse na głosowanie. Te funkcje, wraz z wymogiem, aby wszystkie posty były samodzielne, są jednymi z mocnych stron SO jako platformy, która odróżnia ją od forów. Możesz edytować, aby dodać dodatkowe informacje i / lub uzupełnić wyjaśnienia o dokumentację źródłową.
ysf
1
Zaktualizowano, wyjaśniono nieco więcej. Mam nadzieję, że to pomoże!
Oyebola
0

Bardzo łatwe. Po prostu zmień na () => this.showCancel () jak poniżej:

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

<TouchableHighlight 
    onPress={this.hideCancel()}>
    <View>
        <Text style={styles.cancelButtonText}>Cancel</Text>
    </View>
</TouchableHighlight>
Lim Neo
źródło
musisz sprawdzić ten przykład: Ukryj / pokaż komponenty w
React
0

używam tylko poniższej metody, aby ukryć lub wyświetlić przycisk. mam nadzieję, że ci to pomoże. wystarczy aktualizacja statusu i dodanie 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>)
}
Kiran Chenna
źródło
0

Właściwie w rozwoju iOS, react-nativekiedy używam display: 'none'lub coś takiego jak poniżej:

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

IOS nie ładuje niczego innego z komponentu Image, takiego onLoaditp., Więc zdecydowałem się użyć czegoś takiego jak poniżej:

const styles = StyleSheet.create({
  disappearImage: {
    width: 1,
    height: 1,
    position: 'absolute',
    top: -9000,
    opacity: 0
  }
});
Mehrdad88sh
źródło
0

Jedynym sposobem pokazania lub ukrycia komponentu w React Native jest sprawdzenie wartości parametru stanu aplikacji, takiego jak statelub props. Podałem pełny przykład, jak poniżej:

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;

Oto wynik

Meisam Nazari
źródło
0

Jeśli chcesz to ukryć, ale zachować miejsce zajmowane przez komponent, takie jak visibility: hiddenustawienie css w stylu komponentu, opacity: 0powinno załatwić sprawę.

W zależności od komponentu mogą być wymagane inne kroki w celu wyłączenia funkcji, ponieważ możliwa jest interakcja z niewidocznym elementem.

Gabriel P.
źródło
0

Możesz użyć warunków do pokazania i ukrycia komponentów

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>
    );
  }
Elangovan E.
źródło
-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>
 }

);
}

to wszystko. miłego kodowania ...

mahendren
źródło