Сховати / Показати компоненти в реальній реакції


143

Я дійсно новачок у 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.
Також, як я можу приховати кнопку від самого початку?


вам потрібно ознайомитись із цим прикладом: Сховати / Показати компоненти в реакції рідного
sumit kumar pradhan

Відповіді:


135

Я б зробив щось подібне:

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 ()} це має бути функцією зворотного виклику.
Крісфель

3
Працював для мене лише після зміни return ''наreturn null
k7k0

33
Ви також можете зробити {someBoolVal && <Component />}це, і воно покаже лише, якщо значення bool є істинним.
Nathan Hyland

Це найкраща відповідь
Кирило Гусятин

3
Я не знаю, це прийнята відповідь, яка не реалізує оригінальну бажану функціональність показати / приховати, а натомість додає / видаляє
Мухаммед Ареф

150

У функції візуалізації:

{ 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

2
можливо, це працює? тому що логічно &&не поєднувати елементи{ this.state.showTheThing && (<View><Text>foo</Text><Text>bar</Text></View>)}
мюша

Це працювало для мене, я хотів показати кнопку "Наступний крок", коли користувач завантажив свій профіль. тож мій код був:{this.state.hasPic && <Button title="Go to next step" onPress={this._nextStep} />}
Даггі Бланкс - Дуглас Мвангі

Для всіх, хто бореться з показу кількох компонентів, оберніть його фрагментом. напр. <React.Fragment><Text>Foo</Text><Text>Bar></Text></React.Fragment>
Бен Кулл

48

Якщо реагувати або реагувати нативним, так, як компонент приховати / показати або додати / видалити не працює, як в 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

Ха-ха. Блискуче!
Jaseem Abbas

Це рішення має сенс для випадків використання, коли діалогове вікно потрібно відображати лише за потреби. Ти!
SoundStage

2
Це не спрацює, якщо вам потрібно зберегти статус, вилучити елемент скинути його стан. тому кожен раз, коли ви знову рендеруєте, це як ви створюєте знову компонент.
Даніель Хосе Паділья Пенья

1
вам потрібно ознайомитись із цим прикладом: Сховати / Показати компоненти в реакції рідного
sumit kumar pradhan

20

в render () ви можете умовно показати JSX або повернути null як у:

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

3
У рядку 2 повинні бути
введені дужки

Дякую за найпростіше рішення
Сем

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

екранізація


Це зберігає компоненти в пам'яті, що може бути проблемою з великими компонентами. Чому б не використати великі приклади, наведені вище? Вони вставлять потрібну картинку і повністю видалять іншу ...
AS

4
жоден із цих прикладів не працює належним чином, коли ви намагаєтесь створити анімований спінер. Як я вже згадував у своїй відповіді на Android, намагаючись переключити img на anim gif, це спричинить затримку на 5 секунд, коли не буде показано жодного png, ні gif. Я вважаю, що затримка викликана завантаженням gif в пам'ять, що може зайняти деякий час. Однак, схоже, iOS робить тут набагато кращу роботу. Якщо ви не вірите мені, спробуйте самі.
mauron85

1
Звичайно, як зазначалося, це не оптимальне рішення для кожного компонента. Але IMHO для завантаження прядильника це просто чудово. Врешті-решт він буде завантажений при переході користувача на іншу сторінку.
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 />
Ritveak

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

Макет 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/isissue/18415
Джошуа Пінтер

10

просто використовувати

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

4
Було б корисно, якщо ви додасте якийсь контекст / деталь до відповіді.
UditS

Якщо припустити, що у вас є механізм вирішити, який компонент ховати, ця відповідь є досить корисною. Ви можете обернути будь-який компонент, який ви намагаєтесь приховати, за допомогою View = style = {{width: 0, height: 0}}.
Джош Бейкер

6
як відновити елемент до початкової ширини та висоти?
Деякий Хуан

4
не розумію, чому це спростовується, але в багатьох випадках це корисна порада. Мені потрібно перемикатися між анімованими та неонімованими gif. Умовна комутація img спричиняла затримки без зображення на екрані. У рамках виправлення я показую обидва img, але той, кого слід приховати, має нульову ширину та висоту.
mauron85

Це зберігає компонент у пам'яті, що може бути проблемою з великими компонентами. Чому б не використати великі приклади, наведені вище? Вони вставляють і видаляють компонент повністю ...
AS

6

У мене була така сама проблема, де я хотів би показати / приховати перегляди, але я дійсно не хотів, щоб інтерфейс інтерфейсу стрибав, коли речі додавали / видаляли або обов'язково мали справу з повторним наданням.

Я написав простий Компонент для вирішення цього питання. Анімований за замовчуванням, але простий для перемикання. Я розміщую його на GitHub і NPM з readme, але весь код нижче.

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;

Гарний, просто те, що я шукав :)
Адамскі

Це найкраще працює і поводиться як правильний вигляд, коли ви розміщуєте інші компоненти, які мають життєвий цикл всередині перегляду (з яким не працює visible && (...).
ДБ.

6

Додатковим варіантом є застосування абсолютного позиціонування за допомогою стилізації , встановлення прихованого компонента у позаекранних координатах:

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

На відміну від деяких попередніх пропозицій, це приховає ваш компонент від перегляду, АЛЕ також зробить його (збережіть у DOM), зробивши таким чином справді непомітним .


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

3

Якщо вам потрібен компонент, щоб залишатися завантаженим, але прихованим, ви можете встановити непрозорість на 0. (мені знадобилося це, наприклад, для камери expo)

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

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

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


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

}

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
Хоча цей код може вирішити проблему з ОП, найкраще включити пояснення щодо того, як ваш код вирішує проблему ОП. Таким чином майбутні відвідувачі можуть дізнатисясь із вашої публікації та застосувати її до власного коду. ТАК - це не програма кодування, а ресурс для знань. Крім того, швидше за все буде запрошено високу якість, повну відповідь. Ці функції, поряд з вимогою, що всі повідомлення є автономними, є деякою сильною стороною SO як платформи, що відрізняє її від форумів. Ви можете редагувати, щоб додати додаткову інформацію та / або доповнити свої пояснення джерельною документацією.
ysf

1
Оновлено, пояснили трохи більше. Сподіваюся, це допомагає!
Oyebola

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>

вам потрібно ознайомитись із цим прикладом: Сховати / показати компоненти у реальній реакції
sumit kumar pradhan

0

я просто використовую метод нижче, щоб приховати або переглянути кнопку. сподіваюся, що тобі це допоможе. мені достатньо лише оновити статус і додати 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 не завантажує нічого іншого з компонента Image, наприклад, onLoadтощо, тому я вирішив використовувати щось на зразок нижче:

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

0

Єдиний спосіб показати або приховати компонент у реальній реакції - перевірити значення параметра стану програми, наприклад, 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>
 }

);
}

це все. насолоджуйтесь кодуванням ...

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.