Why doesn't this toggle visibility of React-Native component? - javascript

I'm new to React-Native and looking for a simple, straightforward way to toggle visibility of elements. Why won't this code of mine show/hide the icon? It's a simple useState and useEffect right?
const [isDisabled, setIsDisabled] = React.useState('opacity:0')
React.useEffect(() => {
const emailIsValid = regexEmail.test(email)
console.log(emailIsValid)
if(emailIsValid) {
setIsDisabled('opacity:0')
} else {
setIsDisabled('opacity:100')
}
}, [email])
return (
<View style={styles.container}>
<TextInput
style={styles.textInput}
placeholder="Email address"
value = {email}
onChangeText={text=>setEmail(text)} />
<EvilIcons name="exclamation" size={24} color="orange" style={{isDisabled}}/> /*this one!*/
<TextInput
style={styles.textInput}
placeholder="Password"
value={password}
onChangeText={text=>setPassword(text)}
secureTextEntry />
<TextInput
style={styles.textInput}
placeholder="Confirm password"
value={confirmPassword}
onChangeText={text=>setConfirmPassword(text)}
secureTextEntry />
<Button
disabled={submitDisabled}
style={styles.buttonLogin}
title='Register'
onPress={submitRegister} />
</View>
)

You should not think of it as styles but rather as conditions. Here's an example with a boolean.
const [isDisabled, setIsDisabled] = React.useState(true)
//...
{isDisabled && <EvilIcons name={"exclamation"} size={24} color={"orange"} />}
If you really want to use styles to show/hide the element, you should pass an object to the styles property instead of a string, that's why it isn't working in your example. The styles parameter takes an object not string.
const [isDisabled, setIsDisabled] = React.useState({opacity:0})
//...
<EvilIcons name={"exclamation"} size={24} color={"orange"} style={isDisabled} />
Finally, I think that you must use {} to wrap string type parameters on your EvilIcons component.

The opacity value on your useState is a string, it needs to be a number.
const [isDisabled, setIsDisabled] = React.useState(0);
if(emailIsValid) {
setIsDisabled(0);
} else {
setIsDisabled(100);
}
// ...
return (
<EvilIcons name="exclamation" size={24} color="orange" style={{ opacity: isDisabled }}/>
);

Related

While I hide my password in react-native password freezes to the beginning

const [password, setPassword] = useState('')
const [passwordVisibility, setPasswordVisibility] = useState(false);
<View style={styles.inputContainer}>
<TextInput
name="password"
style={styles.inputField}
autoCapitalize='none'
value={password}
autoCorrect={false}
textContentType="newPassword"
onChangeText={onChangeText}
placeholder="Password"
enablesReturnKeyAutomatically
secureTextEntry={passwordVisibility}
/>
<Pressable onPress={()=>{setPasswordVisibility(!passwordVisibility) , console.log(password)}}>
<Icon name={passwordVisibility == true ? 'eye' : 'eye-off' } size={23} color='purple' />
</Pressable>
</View>
Here is my code .While I hide my password in react-native password freezes to the beginning . How can I fix this
Try changing
onChangeText={onChangeText} to onChangeText={value => setPassword(value)}
and assign the password to the value prop on the TextInput
<TextInput
// current props
onChangeText={value => setPassword(value)}
value={password}
/>

ReactNative TextInput not letting me type

For both iOS and Android simulators
The text just disappears/flickers when I start typing. I tried having an initial state of texts with some value instead of keeping it empty. With this the TextInput sticks to this initial state and does not update itself with new text entered.
I think the state is not updating with 'onChangeText' property, but I am not completely sure.
People have seem to solve this, as they had few typos or missing pieces in code. However I have checked mine thoroughly.
Please help if I have missed anything in the below code.
LoginForm.js
import React, { Component } from 'react';
import { Card, Button, CardSection, Input } from './common';
class LoginForm extends Component {
state = { email: '', password: '' }
render() {
return (
<Card>
<CardSection>
<Input
label="Email"
placeHolder="user#gmail.com"
onChangeText={text => this.setState({ email: text })}
value={this.state.email}
/>
</CardSection>
<CardSection>
<Input
secureTextEntry
label="Password"
placeHolder="password"
onChangeText={text => this.setState({ password: text })}
value={this.state.password}
/>
</CardSection>
<CardSection>
<Button>
Log In
</Button>
</CardSection>
</Card>
);
}
}
export default LoginForm;
Input.js
import React from 'react';
import { TextInput, View, Text } from 'react-native';
const Input = ({ label, value, onChangeText, placeholder, secureTextEntry }) => {
const { inputStyle, labelStyle, containerStyle } = styles;
return (
<View style={containerStyle}>
<Text style={labelStyle}>{label}</Text>
<TextInput
secureTextEntry={secureTextEntry}
placeholder={placeholder}
autoCorrect={false}
style={inputStyle}
value={value}
onChangeText={onChangeText}
/>
</View>
);
};
const styles = {
inputStyle: {
color: '#000',
paddingRight: 5,
paddingLeft: 5,
fontSize: 18,
lineHeight: 23,
flex: 2
},
labelStyle: {
fontSize: 18,
paddingLeft: 20,
flex: 1
},
containerStyle: {
height: 40,
flex: 1,
flexDirection: 'row',
alignItems: 'center'
}
};
export { Input };
The only way to solve this was to change the way the values of TextInput fields are updated, with this code below.
value={this.state.email.value}
value={this.state.password.value}
You problem is how the Input component is written.
There is a render function written inside the stateless component which is not a React class component:
const Input = ({ label, value, onChangeText, placeHolder, secureTextEntry }) => ( // ← remove the wrapping parentheses
{
render() { // <--- this should not be here
↑
const { inputStyle, labelStyle, containerStyle } = styles;
return (
<View style={containerStyle} >
<Text style={labelStyle}>{label}</Text>
<TextInput
secureTextEntry={secureTextEntry}
autoCorrect={false}
placeholder={placeHolder}
style={inputStyle}
onChangeText={onChangeText}
value={value}
underlineColorAndroid="transparent"
/>
</View>
);
}
}
);
Change it to this:
const Input = ({ label, value, onChangeText, placeHolder, secureTextEntry }) => {
const { inputStyle, labelStyle, containerStyle } = styles;
return (
<View style={containerStyle} >
<Text style={labelStyle}>{label}</Text>
<TextInput
secureTextEntry={secureTextEntry}
autoCorrect={false}
placeholder={placeHolder}
style={inputStyle}
onChangeText={onChangeText}
value={value}
underlineColorAndroid="transparent"
/>
</View>
);
};
See running example

Set up React Native children component

I trying to send data trough the props from parent component to children in React Native.
Parent Component
<Card>
<CardSection>
<Input
proportion={5}
label="Email"
/>
</CardSection>
<CardSection>
<Input
proportion={3}
label="Password"
/>
</CardSection>
</Card>
Children Component
const Input = ({ proportion, label }) => {
const { inputStyle } = styles;
inputStyle.flex = proportion;
return (
<View style={containerStyle}>
<Text>{label}</Text>
<TextInput style={inputStyle} />
</View>
);
};
const style = {
inputStyle: {
flex: 2
}
};
And I've got error You attempted set the key 'flex' with the value '3' on an object that is meant to be immutable and has been frozen. Interesting fact, when I've one <Input /> Component everything works fine and set flex: 5, and I reach what I wanted, but with second <Input /> Component I've got error. How I can fix this and set properly?
I think that the good way is to use object spread operator:
const Input = ({ proportion, label }) => {
const { inputStyle } = styles;
return (
<View style={containerStyle}>
<Text>{label}</Text>
<TextInput style={{...inputStyle, flex: proportion}} />
</View>
);
};
const style = {
inputStyle: {
flex: 2
}
};
You define style like const, so you get an error. You can also define it like variable by let.

Passing checkbox value to show / hide Password via react native

I'm using Firebase auth I will want to add a Check box, it will display the password in the password text box and hide it when it is clicked again
How to Passing checkbox value to show / hide Password?
This is my Login Page Code:
export default class Login extends Component {
constructor(props) {
super(props)
this.state = {
email: '',
password: '',
response: ''
}
this.signUp = this.signUp.bind(this)
this.login = this.login.bind(this)
}
async signUp() {
try {
await firebase.auth().createUserWithEmailAndPassword(this.state.email, this.state.password)
this.setState({
response: 'Account Created!'
})
setTimeout(() => {
this.props.navigator.push({
id: 'App'
})
}, 500)
} catch (error) {
this.setState({
response: error.toString()
})
}
}
async login() {
try {
await firebase.auth().signInWithEmailAndPassword(this.state.email, this.state.password)
this.setState({
response: 'user login in'
})
setTimeout(() => {
this.props.navigator.push({
id: 'App'
})
})
} catch (error) {
this.setState({
response: error.toString()
})
}
}
render() {
return (
<View style={styles.container}>
<View style={styles.containerInputes}>
<TextInput
placeholderTextColor="gray"
placeholder="Email"
style={styles.inputText}
onChangeText={(email) => this.setState({ email })}
/>
<TextInput
placeholderTextColor="gray"
placeholder="Password"
style={styles.inputText}
password={true}
secureTextEntry={true}
onChangeText={(password) => this.setState({ password })}
/>
</View>
<TouchableHighlight
onPress={this.login}
style={[styles.loginButton, styles.button]}
>
<Text
style={styles.textButton}
>Login</Text>
</TouchableHighlight>
<TouchableHighlight
onPress={this.signUp}
style={[styles.loginButton, styles.button]}
>
<Text
style={styles.textButton}
>Signup</Text>
</TouchableHighlight>
</View>
)
}
}
import React, {useState} from 'react';
import {TextInput} from 'react-native';
import Icon from 'react-native-vector-icons/FontAwesome5';
const [hidePass, setHidePass] = useState(true);
<TextInput
placeholder="Password"
secureTextEntry={hidePass ? true : false}>
<Icon
name={hidePass ? 'eye-slash' : 'eye'}
onPress={() => setHidePass(!hidePass)} />
<TextInput/>
One way of doing that is to set a state variable like showPassword and toggle it whenever the checkbox is checked. Like so:
import React, { Component } from 'react';
import {
AppRegistry,
Text,
View,
TextInput,
Switch
} from 'react-native';
export default class DemoProject extends Component {
constructor(props) {
super(props);
this.toggleSwitch = this.toggleSwitch.bind(this);
this.state = {
showPassword: true,
}
}
toggleSwitch() {
this.setState({ showPassword: !this.state.showPassword });
}
render() {
return (
<View>
<TextInput
placeholderTextColor="gray"
placeholder="Password"
secureTextEntry={this.state.showPassword}
onChangeText={(password) => this.setState({ password })}
/>
<Switch
onValueChange={this.toggleSwitch}
value={!this.state.showPassword}
/>
<Text>Show</Text>
</View>
)
}
}
AppRegistry.registerComponent('DemoProject', () => DemoProject);
NOTE: This won't work if you set the password prop!!!
So just use a regular TextInput and utilize the secureTextEntry prop.
here is my way of doing it
const LoginScreen = props => {
const [icon, setIcon] = useState("eye-off")
const [hidePassword, setHidePassword] = useState(true)
_changeIcon = () => {
icon !== "eye-off"
? (setIcon("eye-off"), setHidePassword(false))
: (setIcon("eye"), setHidePassword(true))
}
i used native base for textInput
<Input
secureTextEntry={hidePassword}
placeholder="Password"
placeholderTextColor={palette.gray}
/>
<Icon name={icon} size={20} onPress={() => _changeIcon()} />
this will change the secureTextEntry on click
Please correct me if I am wrong, are you asking how to create a check box? If so, you have two routes, either use a 3rd party library from one of the many check boxes on the web or you can create one yourself.
Steps:
download a icon library as such https://github.com/oblador/react-native-vector-icons so you can use the two material design icons from enter link description here eg. checkbox-blank-outline and checkbox-marked to emulate clicked and not clicked
using those two new icons, simply create a new component with what ever functionality you desire and handle all states and such the way you want.
Basic implementation:
Have a state that controls if it was checked or not
Have a onPress function to handle both states and trigger the respective props
// the on press function
onPress = () => {
if (this.sate.checked) {
this.props.checked();
} else {
this.props.unChecked();
}
}
// the rendered component
<Icon name={this.state.checked ? "checkbox-marked" : "checkbox-blank-outline" onPress={this.onPress}/>
this is how i did in simple way,
my checkbox and password component,
<input style={ inputUname } type={this.state.type} placeholder="Password" value={ this.state.password } onChange={this.handlePassword}/>
<Checkbox defaultChecked={false} onSelection={this.showPassword} value="false" name="Checkbox" label="Show password"/>
my state,
this.state = {
type: 'input'
}
here is my show password event,
showPassword(e){
this.setState( { showpassword: !this.state.showpassword }) // this is to change checkbox state
this.setState( { type: this.state.type === 'password' ? 'text' : 'password' }) // this is to change input box type text/password change
}
enter image description here
const [password, setPassword] = useState("")
const [passwordVisible, setPasswordVisible] = useState(true)
<TextInput
mode='outlined'
style={{ flex: 1, marginHorizontal: 20, marginTop: 30 }}
autoCapitalize="none"
returnKeyType="next"
label=' Password '
keyboardType="default"
underlineColorAndroid={'rgba(0,0,0,0)'}
right={<TextInput.Icon color={colors.white} name={passwordVisible ? "eye" : "eye-off"} onPress={onPressEyeButton} />}
text='white'
maxLength={50}
onChangeText={(text) => { setPassword(text) }}
value={password}
defaultValue={password}
theme={styles.textInputOutlineStyle}
secureTextEntry={passwordVisible}
/>
textInputOutlineStyle: {
colors: {
placeholder: colors.white,
text: colors.white,
primary: colors.white,
underlineColor: 'transparent',
background: '#0f1a2b'
}
},
[1]: https://i.stack.imgur.com/C7ist.png
Step1: Create a useState hook to store the initial values of password and secureTextEntry:
const [data, setData] = useState({
password: '',
isSecureTextEntry: true,
});
Step2: Update the state according to the conditions:
<View>
<TextInput
style={styles.textInput}
placeholder="Enter Password"
secureTextEntry={data.isSecureTextEntry ? true : false}
onChangeText={data => {
setData({
password: data,
//OR
/*
//Array destructuring operator to get the existing state i.e
...data
*/
//and then assign the changes
isSecureTextEntry: !data.isSecureTextEntry,
});
}}></TextInput>
<TouchableOpacity
onPress={() => {
setData({
//...data,
isSecureTextEntry: !data.isSecureTextEntry,
});
}}>
<FontAwesome
name={data.isSecureTextEntry ? 'eye-slash' : 'eye'}
color="gray"
size={25}
paddingHorizontal="12%"
/>
</TouchableOpacity>
</View>
<View>
<Input
style={styles.input}
onChangeText={onChangeData}
multiline={false}
secureTextEntry={!showPassword}
textContentType={"password"}
value={data.password}
placeholder="Password"
/>
<TouchableHighlight
style={{
textAlign: "right",
position: "absolute",
right: 20,
bottom: 22,
zIndex: 99999999,
}}
onPress={() => setShowPassword(!showPassword)}
>
<>
{showPassword && (
<Ionicons name="eye-outline" size={22} color="#898A8D" />
)}
{!showPassword && (
<Ionicons name="eye-off-outline" size={22} color="#898A8D" />
)}
</>
</TouchableHighlight>
</View>;

React Native: what is a proper way to pass style as props, when using spread operator on the child component

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.

Categories

Resources