在react native中隐藏/显示组件


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
另外,如何从一开始就隐藏按钮?


Answers:


134

我会做这样的事情:

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

3
仅在更改return ''return null
k7k0

33
您也可以这样做{someBoolVal && <Component />},并且只会在bool值为true时显示。
内森·海兰德

这是最好的答案
Kirill Gusyatin

3
我不知道这是没有实现原始所需功能的显示/隐藏,而是添加/删除的公认答案
Muhammad Aref

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>)}“ bar”之类的操作时会在UI中显示。我希望会显示“ foo”和“ bar”。我需要做的就是打电话给我{ this.state.showTheThing && (<Text>foo</Text>} { this.state.showTheThing && (<Text>bar</Text>}
tonatiuhnb '17

2
也许这可行吗?因为逻辑上&&没有合并元素{ this.state.showTheThing && (<View><Text>foo</Text><Text>bar</Text></View>)}
muescha '17

这对我有用,我想在用户上传个人资料图片时显示一个“下一步”按钮。所以我的代码是:{this.state.hasPic && <Button title="Go to next step" onPress={this._nextStep} />}
Daggie Blanqx-Douglas Mwangi

对于那些努力展示多个组件的人,请用片段包装您的组件。例如。<React.Fragment><Text>Foo</Text><Text>Bar></Text></React.Fragment>
Ben Cull

48

在react或react native中,组件隐藏/显示或添加/删除的方式无法像在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行中
加上

感谢您提供最简单的解决方案
山姆

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切换为动画gif一样,当未显示png或gif时,将导致5s延迟。我认为延迟是由于将gif加载到内存中引起的,这可能需要一些时间。但是,iOS在这里似乎做得更好。如果您不相信我,请自己尝试。
mauron85 '16

1
当然,正如所指出的,这并不是每个组件的最佳解决方案。但是恕我直言,加载微调框就可以了。当用户过渡到另一个页面时,它将最终被卸载。
mauron85 '16

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

但是您不能在JSX内容中编写if / else条件(例如render函数的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})


10

只是使用

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

4
如果您在答案中添加一些上下文/详细信息,将很有帮助。
UditS

假设您具有确定隐藏哪个组件的机制,此答案将非常有用。您可以使用style = {{width:0,height:0}}的View包装要隐藏的任何组件。
乔什·贝克

6
如何将元素恢复为原始的宽度和高度?
一些胡安

4
不明白为什么会这样,但是在很多情况下,这是一个很好的建议。我需要在动画和非动画gif之间切换。有条件地切换img会导致延迟,而屏幕上没有img。作为修复的一部分,我同时显示了img和img,但是应该隐藏的img的宽度和高度均为零。
mauron85'9

这会将组件保留在内存中,这对于大型组件可能是个问题。为什么不使用上面的出色示例?他们完全插入和移除组件...
AS

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

声明可见的false,因此默认情况下模式/视图被隐藏

例子=()=> {

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

6

我在要显示/隐藏视图的问题上遇到了同样的问题,但是我真的不希望在添加/删除或必须处理重新渲染时UI跳动。

我写了一个简单的组件来为我处理。默认为动画,但易于切换。我将它放在自述文件上的GitHubNPM上,但是所有代码都在下面。

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;

好人,正是我所寻找的:)
Adamski

这个工作最好的,像一个真正的视图的行为,当你把有视图内生命周期的其他组件(不工作,visible && (...)
分贝。

6

另一个选项是通过样式应用绝对定位,将隐藏的组件设置在屏幕外坐标中:

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

与先前的一些建议不同,这将从视图中隐藏您的组件,但BUT也会渲染它(将其保留在DOM中),从而使其真正不可见


2
这个想法适合我,谢谢。如果有人需要,也可以看看:gist.github.com/jaysoo/cbb81a07cc22015a72e9
Chaki_Black

3

如果您需要组件保持加载但隐藏状态,则可以将不透明度设置为0。

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

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

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


2

以下示例是使用带有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
尽管此代码可以解决OP的问题,但最好包含有关您的代码如何解决OP的问题的说明。这样,将来的访问者可以从您的帖子中学习,并将其应用于自己的代码。SO不是编码服务,而是知识资源。而且,更可能会推荐高质量,完整的答案。这些功能以及所有职位必须自成体系的要求,是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>


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不会加载Image组件的其他任何内容,例如onLoad或等,因此我决定使用以下内容:

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

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

);
}

就这样。享受您的编码...

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.