Скрыть / показать компоненты в React Native

149

Я новичок в React Native, и мне интересно, как я могу скрыть / показать компонент.
Вот мой тестовый пример:

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

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

У меня есть TextInputкомпонент, и я хочу показать, TouchableHighlightкогда ввод получает фокус, а затем скрыть, TouchableHighlightкогда пользователь нажимает кнопку отмены.

Я не знаю, как «получить доступ» к TouchableHighlightкомпоненту, чтобы скрыть / показать его внутри моих функций showCancel/hideCancel.
Также как я могу скрыть кнопку с самого начала?

Crysfel
источник

Ответы:

140

Я бы сделал что-то вроде этого:

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
Большое вам спасибо за это, всего одно небольшое изменение, которое мне нужно было сделать: onFocus = {() => this.showCancel ()}, это должна быть функция обратного вызова.
Crysfel
4
Только работал для меня после того, изменяя return ''кreturn null
k7k0
35
Вы также можете сделать это, {someBoolVal && <Component />}и он будет отображаться только в том случае, если значение bool истинно.
Nathan Hyland
Это лучший ответ
Кирилл Гусятин
3
Я не знаю, что это принятый ответ, который не реализует исходную желаемую функциональность показать / скрыть, а вместо этого добавляет / удаляет
Мухаммад Ареф
155

В вашей функции рендеринга:

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

Тогда просто сделайте:

this.setState({showTheThing: true})  // to show it  
this.setState({showTheThing: false}) // to hide it
Кришан Гупта
источник
2
Это сработало для меня. Однако я не уверен, почему, когда я делаю что-то вроде, { this.state.showTheThing && (<Text>foo</Text> && <Text>bar</Text>)}в пользовательском интерфейсе отображается только «полоса». Я ожидал, что будут отображаться «foo» и «bar». Что мне нужно сделать, чтобы решить эту проблему, так это позвонить{ this.state.showTheThing && (<Text>foo</Text>} { this.state.showTheThing && (<Text>bar</Text>}
tonatiuhnb
3
может это работает? потому что логическое &&не совмещает элементы{ this.state.showTheThing && (<View><Text>foo</Text><Text>bar</Text></View>)}
muescha
Это сработало для меня, я хотел показать кнопку «Следующий шаг», когда пользователь загружает свой профиль. так что мой код был:{this.state.hasPic && <Button title="Go to next step" onPress={this._nextStep} />}
Daggie Blanqx - Douglas
1
Для тех, кто борется с отображением более одного компонента, оберните свой компонент фрагментом. например. <React.Fragment><Text>Foo</Text><Text>Bar></Text></React.Fragment>
Бен
50

При реагировании или реагировании нативный способ скрытия / отображения или добавления / удаления компонента не работает, как в Android или iOS. Большинство из нас думает, что могла бы быть похожая стратегия вроде

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

А вот способ реагирования на родную работу совершенно другой. Единственный способ достичь такой функциональности - включить ваш компонент в DOM или удалить из DOM.

В этом примере я собираюсь установить видимость текстового представления на основе нажатия кнопки.

введите описание изображения здесь

Идея, лежащая в основе этой задачи, заключается в создании переменной состояния с именем state, имеющей начальное значение, установленное в false, когда происходит событие нажатия кнопки, а затем значение переключается. Теперь мы будем использовать эту переменную состояния при создании компонента.

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

единственное, что следует отметить в этом фрагменте, - это то, renderIfчто на самом деле является функцией, которая возвращает переданный ей компонент на основе переданного ей логического значения.

renderIf(predicate)(element)

renderif.js

'use strict';
const isFunction = input => typeof input === 'function';
export default predicate => elemOrThunk =>
  predicate ? (isFunction(elemOrThunk) ? elemOrThunk() : elemOrThunk) : null;
Раджан Тванабашу
источник
Умно :) какой вариант использования преобразователя?
goldylucks
Ха-ха. Гениально!
Джасим Аббас
Это решение имеет смысл для случаев использования, когда диалоговое окно необходимо отображать только при необходимости. Тай!
SoundStage
2
Это не сработает, если вам нужно сохранить статус, удалить элемент, сбросить его состояние. поэтому каждый раз при повторном рендеринге вы снова создаете компонент.
Даниэль Хосе Падилья Пенья
20

в render () вы можете условно показать JSX или вернуть null, как в:

render(){
    return({yourCondition ? <yourComponent /> : null});
}
Мар
источник
3
Скобки должны быть обязательными в строке 2.
jiexishede
Спасибо за простейшее решение
Сэм
13

Мне нужно было переключаться между двумя изображениями. При условном переключении между ними была задержка 5 секунд, и изображение не отображалось.

Я использую подход из отклоненного ответа amos. Публикация как новый ответ, потому что сложно добавить код в комментарий с правильным форматированием.

Функция рендеринга:

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

Стили:

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

скринкаст

mauron85
источник
Это сохраняет компоненты в памяти, что может быть проблемой для больших компонентов. Почему бы не использовать отличные примеры выше? Они вставят правую картинку и полностью удалят другую ...
AS
4
любой из этих примеров не работает должным образом, когда вы пытаетесь создать анимированный счетчик. Как я уже упоминал в своем ответе на android, попытка переключить img на anim gif вызовет задержку 5 секунд, если не отображаются ни png, ни gif. Я считаю, что задержка вызвана загрузкой gif в память, что может занять некоторое время. Однако, похоже, здесь iOS работает намного лучше. Если вы мне не верите, попробуйте сами.
mauron85 05
1
Конечно, как уже отмечалось, это не оптимальное решение для каждого компонента. Но ИМХО для загрузки спиннера это нормально. В конечном итоге он будет выгружен при переходе пользователя на другую страницу.
mauron85
13

Чаще всего я делаю что-то вроде этого:

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

Если вы новичок в программировании, эта строка должна показаться вам странной:

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

Эта строка эквивалентна

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

Но вы не можете записать условие if / else в JSX-контент (например, часть return () функции рендеринга), поэтому вам придется использовать эту нотацию.

Этот небольшой трюк может быть очень полезным во многих случаях, и я предлагаю вам использовать его в ваших разработках, потому что вы можете быстро проверить условие.

С Уважением,

КуроАку
источник
Не могли бы вы подробнее рассказать, как вы определили <ToHideAndShowComponent />
Ритвеак
13

Макет React Native имеет displayподдержку свойств, аналогичную CSS. Возможные значения: noneи flex(по умолчанию). https://facebook.github.io/react-native/docs/layout-props#display

<View style={{display: 'none'}}> </View>
Эстеван Лукас
источник
2
Осторожно, чтобы не использовать это position: absolute, на самом деле он этого не скрывает! Известная ошибка от 0,54 до 0,59 (как минимум): github.com/facebook/react-native/issues/18415
Джошуа Пинтер,
12

введите описание изображения здесь

Скрыть и показать родительский видActivity Indicator

constructor(props) {
  super(props)

  this.state = {
    isHidden: false
  }  
} 

Скрыть и показать как подписку

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

Полная ссылка

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

Нажатие кнопки устанавливает состояние, как показано ниже

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

Когда тебе нужно спрятаться

this.setState({isHidden: false})
Харшал Валанда
источник
11

просто используйте

style={ width:0, height:0 } // to hide
Амос
источник
4
Было бы полезно, если бы вы добавили к ответу контекст / детали.
UditS
Предполагая, что у вас есть механизм, позволяющий решить, какой компонент скрывать, этот ответ весьма полезен. Вы можете обернуть любой компонент, который вы пытаетесь скрыть, представлением со стилем = {{width: 0, height: 0}}.
Джош Бейкер
6
как восстановить исходную ширину и высоту элемента?
Some Juan
4
не понимаю, почему это отвергается, но во многих случаях это хороший совет. Мне нужно переключаться между анимированным и неанимированным gif. Условное переключение img вызывало задержки без img на экране. В рамках исправления я показываю оба img, но тот, который должен быть скрыт, имеет нулевую ширину и высоту.
mauron85
Это сохраняет компонент в памяти, что может быть проблемой для больших компонентов. Почему бы не использовать отличные примеры выше? Они полностью вставляют и удаляют компонент ...
AS
6

У меня была такая же проблема, когда я хотел бы показать / скрыть представления, но я действительно не хотел, чтобы пользовательский интерфейс прыгал, когда что-то было добавлено / удалено или обязательно для повторного рендеринга.

Я написал простой компонент, чтобы справиться с этим за меня. По умолчанию анимирован, но легко переключаться. Я выложил его на GitHub и NPM с ридми, но весь код ниже.

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
источник
Хороший, именно то, что я искал :)
Адамски
Это работает лучше всего и ведет себя как правильное представление, когда вы помещаете в представление другие компоненты, имеющие жизненный цикл (что не работает с visible && (...).
дБ.
6

Дополнительная опция - применить абсолютное позиционирование с помощью стиля , установив скрытый компонент в координатах вне экрана:

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

В отличие от некоторых из предыдущих предложений, это скроет ваш компонент из поля зрения, НО также отрендерит его (сохраните в DOM), тем самым сделав его действительно невидимым .

d4vidi
источник
2
Мне эта идея подходит, спасибо. Если кому-то нужно, посмотрите и на это: gist.github.com/jaysoo/cbb81a07cc22015a72e9
Chaki_Black
5
constructor(props) {
    super(props);
    this.state = {
      visible: true,
}
}

объявить видимым ложным, поэтому по умолчанию модальные / вид скрыты

example = () => {

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

}

** Вызов функции **

{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> 
 }
Шиво'хам 0
источник
4

Если вам нужно, чтобы компонент оставался загруженным, но скрытым, вы можете установить непрозрачность на 0. (мне это нужно, например, для камеры экспонирования)

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

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

//when you want to hide
this.setState({opacity: 0})
ykay говорит: "Восстановить Монику"
источник
3
// 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
источник
3
Хотя этот код может решить проблему OP, лучше всего включить объяснение того, как ваш код решает проблему OP. Таким образом, будущие посетители могут узнать из вашего сообщения и применить его к своему собственному коду. SO - это не сервис кодирования, а ресурс знаний. Кроме того, больше шансов получить качественные и полные ответы. Эти функции, наряду с требованием, чтобы все сообщения были автономными, являются одними из сильных сторон SO как платформы, которые отличает ее от форумов. Вы можете редактировать, чтобы добавить дополнительную информацию и / или дополнить свои пояснения исходной документацией.
ysf
1
Обновил, объяснил еще немного. Надеюсь, это поможет!
Оебола,
2

Вы можете использовать мой модуль response-native-display для отображения / скрытия компонентов.

Дэнни Михаэли
источник
2

Следующий пример - это машинописное кодирование с помощью хуков.

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
источник
0

Очень просто. Просто измените на () => this.showCancel (), как показано ниже:

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

<TouchableHighlight 
    onPress={this.hideCancel()}>
    <View>
        <Text style={styles.cancelButtonText}>Cancel</Text>
    </View>
</TouchableHighlight>
Лим Нео
источник
0

Я просто использую метод ниже, чтобы скрыть или просмотреть кнопку. надеюсь, это поможет вам. мне достаточно просто обновить статус и добавить 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

Собственно, в разработке iOS, react-nativeкогда я использую display: 'none'или что-то вроде ниже:

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

IOS не загружает ничего другого из компонента изображения, например, onLoadи т.д., поэтому я решил использовать что-то вроде ниже:

const styles = StyleSheet.create({
  disappearImage: {
    width: 1,
    height: 1,
    position: 'absolute',
    top: -9000,
    opacity: 0
  }
});
Mehrdad88sh
источник
0

Единственный способ показать или скрыть компонент в react native - это проверить значение параметра состояния приложения, например stateили props. Я привел полный пример, как показано ниже:

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;

Вот результат

Мейсам Назари
источник
0

Если вы хотите скрыть это, но оставить пространство, занимаемое компонентом, например, visibility: hiddenнастройка css в стиле компонента, opacity: 0должна помочь.

В зависимости от компонента могут потребоваться другие шаги по отключению функциональности, поскольку возможно взаимодействие с невидимым элементом.

Габриэль П.
источник
0

Вы можете использовать условия для отображения и скрытия компонентов

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

);
}

вот и все. наслаждайтесь кодированием ...

Махендрен
источник