1.Here is my custom text input custom component i define props ref which i want to use in
parent component
export const InputField = ({
placeholder,
onChangeText,
placeholderTextColor,
showSecureIcon,
isSecure,
onPressIcon,
keyboardType,
returnKeyType,
maxLength,
secureIconColor,
handleUseCallBack,
ref,
value
}) => {
return (
<View style={styles.container}>
<TextInput
style={styles.input}
placeholder={placeholder}
onChangeText={onChangeText}
placeholderTextColor={placeholderTextColor}
autoCapitalize="none"
secureTextEntry={isSecure}
keyboardType={keyboardType}
returnKeyType={returnKeyType}
maxLength={maxLength}
value={value}
ref={ref}
/>
<View style={styles.iconContainer}>
{showSecureIcon ?
<TouchableOpacity
onPress={onPressIcon}
>
<Ionicons
name={isSecure ? "eye-off-sharp" : "eye-sharp"}
color={secureIconColor}
size={constants.vw(25)}
/>
</TouchableOpacity>
:
null
}
</View>
</View>
)
}
2-Now the part where i want to change my ref
in this field i create the text inputs field of password and confirm where i want to change
my focus
const passwordRef = useRef(null);
const confirmPasswordRef =
useRef(null);
const onSubmitEditing=()=>{
confirmPasswordRef.current.focus();
}
<View style={{ marginTop: constants.vh(66) }}>
<Components.InputField
placeholder={constants.ConstStrings.setANewPassword}
ref={passwordRef}
onSubmitEditing={()=>onSubmitEditing()}
onChangeText={(text) => setState({
...state,
password: text
})}
/>
</View>
<View style={{ marginTop: constants.vh(20) }}>
<Components.InputField
ref={confirmPasswordRef}
placeholder={constants.ConstStrings.confirmPassword}
onChangeText={(text) => setState({
...state,
confirm_password: text
})}
/>
</View>
This part is the end part qwertyuiopsdf;';dsyuiopoiuteweryuiopuytreep[gfjklvcvbnm,mvcxzxcewqwe[poiuyd
The problem with your code is that you've created a custom input component, but haven't given to it the instructions on how to handle different methods.
So, in your case, the generic Input component knows what method is focus, but your custom one doesn't.
What you should do:
Make your input component a forwardRef one so that you can pass a ref to it and then be able to do actions on it.
Use useImperativeHandle so that you can call internal methods of your ref.
Create a focus fn which in your custom input will basically call the focus method of your ref.
You cannot pass the ref in props as you are doing, that just doesn't work in React.
I suppose all of your components are functional, in that case:
export const InputField = React.forwardRef({
placeholder,
...
}, ref) => { // pass a ref to here, this way you will let React know to associate the ref from external component to an internal ref
const textInput = useRef(null); // Create a ref to pass to your input
useImperativeHandle(ref, () => ({ // To be able to call `focus` from outside using ref
focus,
});
const focus = textInput.current.focus();
return (
<View style={styles.container}>
<TextInput
ref={textInput}
style={styles.input}
...
/>
...
</View>
)
}
And then in your component you just have to pass a fresh ref created by useRef and then you'll be able to call focus on in.
Tell me whether that solves it for you!
This is my component A:
const GenericTextInput = (props) => {
return (
<TextInput
style={styles.input}
{...props}
/>
);
};
This is my component B:
const SignIn = (props) => {
return (
<View>
<GenericTextInput
placeholder="Email"
autoFocus={true}
keyboardType="email-address"
returnKeyType="next"
autoCorrect={false}
placeholderTextColor='rgba(250,248,244, .4)'
underlineColorAndroid='rgba(250,248,244, .7)'
/>
<GenericTextInput
placeholder="Password"
placeholderTextColor='rgba(250,248,244, .4)'
underlineColorAndroid='rgba(250,248,244, .7)'
secureTextEntry={true}
/>
</View>
);
};
I want to add a specific styling to the 2nd GenericTextInput in my component B. In the component A I want to use the spread operator (it is so convenient).
If I simply make:
//component A
const GenericTextInput = (props) => {
return (
<TextInput
style={[styles.input, props.styles]}
{...props}
/>
);
};
//component B
const SignIn = (props) => {
return (
<View>
<GenericTextInput
placeholder="Email"
autoFocus={true}
keyboardType="email-address"
returnKeyType="next"
autoCorrect={false}
placeholderTextColor='rgba(250,248,244, .4)'
underlineColorAndroid='rgba(250,248,244, .7)'
/>
<GenericTextInput
placeholder="Password"
placeholderTextColor='rgba(250,248,244, .4)'
underlineColorAndroid='rgba(250,248,244, .7)'
secureTextEntry={true}
style={styles.customStyleForSecondInput}
/>
</View>
);
};
I'll have 2 style props in comp. A, and the second style prop will completely overwrite the first one.
What is the proper way of adding a specific styling to the 2nd GenericTextInput?
I usually destructure the named property (style) out for the object, and use the rest operator to collect the remaining props into a new object:
const {style, ...rest} = props;
return (
<TextInput
style={[styles.input, style]}
{...rest}
/>
)
Note that this requires the transform-object-rest-spread Babel plugin. This plugin is included in the React Native Babel preset, so it will work out of the box -- but may not work in other JavaScript environments without this plugin.
If you want your custom styles to completely overwrite the preset ones, I believe you can do something like
style={props.style || styles.input}
but I think you're asking how to have the custom styles overwrite some of the preset ones. In that case it would be
style={[styles.input, props.style]}
since you're passing the property down as 'style' not 'styles' you just drop the s at the end.
I'm really new to React Native and I'm wondering how can I hide/show a component.
Here's my test case:
<TextInput
onFocus={this.showCancel()}
onChangeText={(text) => this.doSearch({input: text})} />
<TouchableHighlight
onPress={this.hideCancel()}>
<View>
<Text style={styles.cancelButtonText}>Cancel</Text>
</View>
</TouchableHighlight>
I have a TextInput component, what I want is to show the TouchableHighlight when the input gets the focus, then hide the TouchableHighlight when the user press the cancel button.
I donĀ“t know how to "access" the TouchableHighlight component in order to hide/show it inside of my functions showCancel/hideCancel.
Also, how can I hide the button from the very beginning?
In your render function:
{ this.state.showTheThing &&
<TextInput/>
}
Then just do:
this.setState({showTheThing: true}) // to show it
this.setState({showTheThing: false}) // to hide it
I would do something like this:
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()}
);
}
});
In react or react native the way component hide/show or add/remove does not work like in android or iOS. Most of us think there would be the similar strategy like
View.hide = true or parentView.addSubView(childView)
But the way react native work is completely different. The only way to achieve this kind of functionality is to include your component in your DOM or remove from DOM.
Here in this example I am going set the visibility of text view based on the button click.
The idea behind this task is the create a state variable called state having the initial value set to false when the button click event happens then it value toggles. Now we will use this state variable during the creation of component.
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>
);
}
}
the only one thing to notice in this snippet is renderIf which is actually a function which will return the component passed to it based on the boolean value passed to it.
renderIf(predicate)(element)
renderif.js
'use strict';
const isFunction = input => typeof input === 'function';
export default predicate => elemOrThunk =>
predicate ? (isFunction(elemOrThunk) ? elemOrThunk() : elemOrThunk) : null;
React Native's layout has the display property support, similar to CSS.
Possible values: none and flex (default).
https://facebook.github.io/react-native/docs/layout-props#display
<View style={{display: 'none'}}> </View>
in render() you can conditionally show the JSX or return null as in:
render(){
return({yourCondition ? <yourComponent /> : null});
}
Most of the time i'm doing something like this :
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>
);
}
}
If you're kind of new to programming, this line must be strange to you :
{this.state.isHidden ? <ToHideAndShowComponent/> : null}
This line is equivalent to
if (this.state.isHidden)
{
return ( <ToHideAndShowComponent/> );
}
else
{
return null;
}
But you can't write an if/else condition in JSX content (e.g. the return() part of a render function) so you'll have to use this notation.
This little trick can be very useful in many cases and I suggest you to use it in your developments because you can quickly check a condition.
Regards,
EDIT: For a more straight forward synthax, you can do {this.state.isHidden && <ToHideAndShowComponent/>}. Here, the left operand is evaluated before the right one, so if isHidden is false, then the component will not show up.
just use
style={ width:0, height:0 } // to hide
I needed to switch between two images. With conditional switching between them there was 5sec delay with no image displayed.
I'm using approach from downvoted amos answer. Posting as new answer because it's hard to put code into comment with proper formatting.
Render function:
<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>
Styles:
var styles = StyleSheet.create({
logo: {
width: 200,
height: 200,
},
hidden: {
width: 0,
height: 0,
},
});
Hide And Show parent view of Activity Indicator
constructor(props) {
super(props)
this.state = {
isHidden: false
}
}
Hide and Show as Follow
{
this.state.isHidden ? <View style={style.activityContainer} hide={false}><ActivityIndicator size="small" color="#00ff00" animating={true}/></View> : null
}
Full reference
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>
);
}
On Button presss set state as follow
onSignupPress() {
this.setState({isHidden: true})
}
When you need to hide
this.setState({isHidden: false})
I had the same issue where I would want to show / hide Views, but I really didn't want the UI jumping around when things were added/removed or necessarily to deal with re-rendering.
I wrote a simple Component to deal with it for me. Animated by default, but easy to toggle. I put it on GitHub and NPM with a readme, but all the code is below.
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;
An additional option is to apply absolute positioning via styling, setting the hidden component in out-of-screen coordinates:
<TextInput
onFocus={this.showCancel()}
onChangeText={(text) => this.doSearch({input: text})}
style={this.state.hide ? {position: 'absolute', top: -200} : {}}
/>
Unlike in some of the previous suggestions, this would hide your component from view BUT will also render it (keep it in the DOM), thus making it truly invisible.
constructor(props) {
super(props);
this.state = {
visible: true,
}
}
declare visible false so by default modal / view are hide
example = () => {
this.setState({ visible: !this.state.visible })
}
**Function call **
{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>
}
If you need the component to remain loaded but hidden you can set the opacity to 0. (I needed this for expo camera for instance)
//in constructor
this.state = {opacity: 100}
/in component
style = {{opacity: this.state.opacity}}
//when you want to hide
this.setState({opacity: 0})
Three ways to show\hide components:
- Class Component: / ------------------------------------------------------------------------------------------------------------
in all examples i used below state:
.
...
constructor(props) {
super(props);
this.state = {showComponent: true};
}
1. using display prop
<View display={this.state.showComponent ? 'flex' : 'none'} />
2. using display prop with style
<View style={{display:this.state.showComponent ? 'flex' : 'none'}} />
3. limit render
{
this.state.showComponent &&
<View /> // Or <View> ... </View>
}
- Functional Component:/ ------------------------------------------------------------------------------------------------------------
in all examples i used below state:
const [showComponent, setShowComponent] = useState(true);
1. using display prop
<View display={showComponent ? 'flex' : 'none'} />
2. using display prop with style
<View style={{showComponent ? 'flex' : 'none'}} />
3. limit render
{
showComponent &&
<View /> // Or <View> ... </View>
}
// 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)}}/>
I usually use something like this
const [showComponent, setShowComponent] = useState(false)
return(
<div>
{showComponent && (<Text>Hello</Text>)}
<Button onPress={() => {setShowComponent(true)}}>Click me</Button>
</div>
)
It will show 'Hello' once the button is pressed. This is called conditional rendering. You can refer to w3schools to learn about conditional rendering.
You can use my module react-native-display to show/hide components.
The following example is coding in typescript with 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>
......
}
I would vouch for using the opacity-method if you do not want to remove the component from your page, e.g. hiding a WebView.
<WebView
style={{opacity: 0}} // Hide component
source={{uri: 'https://www.google.com/'}}
/>
This is useful if you need to submit a form to a 3rd party website.
i am just using below method to hide or view a button. hope it will help you. just updating status and adding hide css is enough for me
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>)
}
Actually, in iOS development by react-native when I use display: 'none' or something like below:
const styles = StyleSheet.create({
disappearImage: {
width: 0,
height: 0
}
});
The iOS doesn't load anything else of the Image component like onLoad or etc, so I decided to use something like below:
const styles = StyleSheet.create({
disappearImage: {
width: 1,
height: 1,
position: 'absolute',
top: -9000,
opacity: 0
}
});
If you want to hide it but keep the space occupied by the component like css's visibility: hidden setting in the component's style opacity: 0 should do the trick.
Depending on the component other steps in disabling the functionality might be required as interaction with an invisible item is possible.
Very Easy. Just change to () => this.showCancel() like below:
<TextInput
onFocus={() => this.showCancel() }
onChangeText={(text) => this.doSearch({input: text})} />
<TouchableHighlight
onPress={this.hideCancel()}>
<View>
<Text style={styles.cancelButtonText}>Cancel</Text>
</View>
</TouchableHighlight>
The only way to show or hide a component in react native is checking a value of a parameter of app state like state or props. I provided a complete example as below:
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;
You can use the conditions for show and hide the components
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>
);
}
I solve this problem like this:
<View style={{ display: stateLoad ? 'none' : undefined }} />
Just simply use this because I wanted to use the "useRef" conditions were not an option for me. You can use this suppose when you want to use useRef hook and press the button.
<Button
ref={uploadbtn}
buttonStyle={{ width: 0, height: 0, opacity: 0, display: "none" }}
onPress={pickImage}
/>
We now have hooks so I would recommend a reformat. Use hooks to turn components on/off.
const [modalVisible, setModalVisible] = setState(false);
Then have a button
<Button title="Press Me" onPress={() => {
setModalVisible(true);
}}
Then, inside your return statement
return(
<View>
{modalVisible &&
Insert modal code in here.
}
</View>
)
You can do it, using the useState Hook
The useState basically, is a feature which helps us preserve the values of variables even after multiple re-renders.
It acts a local state management tool, for storing values, after the component renders or re-renders.
In addition, to that you can also, trigger it to update the UI, by changing the value of the state variable.
const [show,setShow] = useState(true)
So, here we have destructured the, values that useState sends, first is the variable, through which we can get the value, and the second is a function through which we can update the state variables value.
So, in your case -
import React, {useState} from 'react';
import { Text, View, StyleSheet,Button } from 'react-native';
import Constants from 'expo-constants';
export default function App() {
const [show,setShow] = useState(true)
return (
<View style={styles.container}>
{show && <Text style={styles.paragraph}>
Showing and Hiding using useState
</Text>}
<Button
title="Press me"
onPress={() => {setShow(!show)}}
/>
</View>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
paddingTop: Constants.statusBarHeight,
backgroundColor: '#ecf0f1',
padding: 8,
},
paragraph: {
margin: 24,
fontSize: 18,
fontWeight: 'bold',
textAlign: 'center',
},
});
In this example, on Button press, we are toggling the state variable from true to false.
You can show or hide JSX Code, using boolean conditions, which we are doing in this statement.
{show && <Text style={styles.paragraph}>
Showing and Hiding using useState
</Text>}
This is an quick and effective method of using state for UI manipulations.
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>
}
);
}
thats all. enjoy your coding...