I have the following set up, with all the methods with .bind(this) in the constructor. So the user enters in username and password in the inputs and get updated in state, and the component gets re-rerendered and newly updated state this.props.username and this.props.password get passed down. I would then want to pass them into an action creator called this.props.registerUser() once Register button is clicked.
So I was wondering, what's the right practice to pass in the newly updated props to an action creator?
For example
Is it _handleRegister(this.props.username, this.props.password) then this.props.registerUser(this.props.username, this.props.password)? Or simply this.props.registerUser(this.props.username, this.props.password)? Or a combination of this._handleRegister(this.props.username, this.props.password) and former?
_handleRegister() {
this.props.registerUser()
}
render() {
return (
<View>
<TextInput
placeholder={'Username'}
onChangeText={...}
value={this.props.username}
/>
<TextInput
placeholder={'Password'}
onChangeText={...}
value={this.props.password}
/>
<TouchableHighlight onPress={this._handleRegister}>
<Text>Register</Text>
</TouchableHighlight>
</View>
)
}
}
Thank you
You don't need to pass prameters to _handleRegister
_handleRegister() {
const { username, password, registerUser } = this.props;
registerUser(username, password);
}
Additional tip: you can skip return keyword by doing:
render() (
<View>
...
</View>
)
Related
I tried creating a reusable component in React. Which has a textInput and secure text entry handled in the state of the reusable component. But the state is not getting maintained differently when reusing always the last state is updated,
Issue: If i call the reusable const two times on a single screen or on the next screen in stack. The toggle for secure entry keeps changing for the last field loaded and earlier loaded fields state is lost.
i.e., when i click on toggle of Password, text change from hidden to visible or vice-versa happens for Confirm password field.
This is how i call
<View style={styles.inputContainerView}>
<InputTextFieldView
enteredText={passwordEntered}
setEnteredText={setPasswordEntered}
title={Constants.registerPasswordPlaceholder} icon={lockIcon}
isSecureEntry={true}
placeholder={Constants.registerPasswordPlaceholder} />
</View>
<View style={styles.inputContainerView}>
<InputTextFieldView
enteredText={confirmPasswordEntered}
setEnteredText={setConfirmPasswordEntered}
title={Constants.registerConfirmPasswordPlaceholder} icon={lockIcon}
isSecureEntry={true}
placeholder={Constants.registerConfirmPasswordPlaceholder} />
</View>
My component:
const InputTextFieldView = ({ enteredText, setEnteredText, title, icon, isSecureEntry, placeholder }) => {
const [isSecureEntryEnabled, setIsSecureEntryEnabled] = useState(isSecureEntry)
const eyeOpenIcon = require('../../../assets/visibility.png')
const eyeCloseIcon = require('../../../assets/close-eye.png')
useEffect(() => {
console.log('called')
}, [])
toggleSecureTextEntry = () => {
console.log('title', title)
setIsSecureEntryEnabled(!isSecureEntryEnabled)
}
return (
<View style={styles.fieldsContainerView}>
<Text style={styles.titleStyle}>{title}</Text>
<View style={[styles.fieldInputContainerView, {padding: Platform.OS === 'ios' ? 12 : 0}]}>
<Image source={icon} style={styles.fieldIconView} />
<TextInput secureTextEntry={isSecureEntryEnabled} style={{ width: isSecureEntry ? '75%' : '85%' }} onChange={() => setEnteredText()} value={enteredText} placeholder={placeholder} />
{isSecureEntry &&
<TouchableWithoutFeedback onPress={() => toggleSecureTextEntry()}>
<Image source={isSecureEntryEnabled ? eyeOpenIcon : eyeCloseIcon} style={styles.fieldIconView} />
</TouchableWithoutFeedback>
}
</View>
</View>
)
}
I'm guessing that you are using isSecureEntry as the hook to toggle the password fields? If so, it looks like you are passing the same state to both
the password field and the confirm password field. Right now, you essentially have one light switch that controls two different lamps. So you are going to want to have separate separate useState hooks for the password field and confirm password field. Then pass each one to the correct component.
const [passwordSecure, togglePasswordSecure] = useState(true);
const [confirmPasswordSecure, toggleConfirmPasswordSecure] = useState(true);
const togglePasswordField = () => {
togglePasswordSecure(!passwordSecure)
};
const toggleConfirmPasswordField = () => {
toggleConfirmPasswordSecure(!confirmPasswordSecure)
};
Issue was happening due to TouchableWithoutFeedback. Now used TouchableOpacity and it started to work. Not sure why but it may help someone
I am new to react-native and I am using reanimated-bottom sheet in my project and I want to control this from other functional component called as Comment.
in my main component I am passing the reference of the sheet as
<Comment ref={ref} />
but when I receive it in my comment component it says cant find variable ref
const Comment =({ref}) => {
....
<TouchableOpacity
style={styles.panelButton}
onPress={() => ref.current.snapTo(1)}>
<Text>Cancel</Text>
</TouchableOpacity>
</View>
...
}
all I want is to close the sheet from my comment component without changing it to class component.
ref is predefined property so it won't be passed to the component.
You'd better use callback instead of passing ref.
<Component ref={ref} onPressButton={() => { ref.current.snapTo(1) }} />
const Comment =({ onPressButton }) => {
....
<TouchableOpacity
style={styles.panelButton}
onPress={onPressButton}>
<Text>Cancel</Text>
</TouchableOpacity>
....
}
Summary
I have a react native functional component where I collect a value from the user in TextInput and then need to pass that value to a function when a button is pressed. I know how to do this in a react native class component with state, however I'm trying to use a functional component.
I'm close to figuring it out but I'm just missing something. The code I have so far is below.
saveUserInput handles saves the text from the user and returns input. When I pass saveUserInput into forgotPassword, which is my function that sends userInput to my backend to reset password, saveUserInput is defined as the function as opposed to the value it returns. How can make this work as a functional component?
Code
export default (ForgotPasswordScreen = () => {
const saveUserInput = userInput => {
const input = userInput;
return input;
};
return (
<View style={styles.container}>
<Text style={styles.headerText}>Forgot Password</Text>
<Text style={styles.forgotText}>
Enter your username or email address below to reset your password
</Text>
<TextInput
onChangeText={userInput => saveUserInput(userInput)}
placeHolder={"username or email"}
/>
<Text
style={styles.buttonText}
onPress={saveUserInput => forgotPassword(saveUserInput)}
>
Forgot Password Button
</Text>
</View>
);
});
export default (ForgotPasswordScreen = () => {
let input = '';
const saveUserInput = userInput => {
input = userInput;
};
return (
<View style={styles.container}>
<Text style={styles.headerText}>Forgot Password</Text>
<Text style={styles.forgotText}>
Enter your username or email address below to reset your password
</Text>
<TextInput
onChangeText={userInput => saveUserInput(userInput)}
placeHolder={"username or email"}
/>
<Text
style={styles.buttonText}
onPress={() => forgotPassword(input)}
>
Forgot Password Button
</Text>
</View>
);
});
This should do the trick without using hooks. Pull out the input variable to be in scope for all other components to use.
But life could be much easier using useState hooks.
I'm using React native and I want to use Redux-Form to submit text from TextInput following this article,
It works as expected if I enter the text, but when I set the value property of TextInput to some string, after submitting I get an empty object.
It only works when I enter the text, but not when I set it to some value.
here is the part of the TextInput I use:
const titleField = (input, inputProps) => {
var myval = 'test';
return (
<View style={{flexDirection: 'row'}}>
<Label style={{padding: 5}}>Task Title:</Label>
<TextInput
style={styles.inputStyle}
{...inputProps}
onChangeText={input.onChange}
onBlur={input.onBlur}
onFocus={input.onFocus}
value={myval} // get {} when checking the log input after submitting
/>
</View>
)
}
Hope you can help me with that,
Thank you.
I solved this by changing the functional component to a class component and used componentDidUpdate() lifecycle method to check if the props has changed when passing them to the component and call this.props.input.onChange(this.props.value); because input can be invoked with a value also, therefore this.props.value is passed.
From Redux Form API (Field Component):
input.onChange(eventOrValue)
A function to call when the form field is changed. It expects to either receive the React SyntheticEvent or the new value of the field.
This is the whole class component:
class CounterField extends React.Component {
constructor(props){
super(props);
}
componentDidUpdate(){
this.props.input.onChange(this.props.value);
}
render(){
return (
<View style={{paddingTop: 20, width: 30}}>
<TextInput
name='title'
onChangeText={this.props.input.onChange}
editable={false}
value={this.props.value}
style={{fontSize: 20, textAlign: 'center', fontWeight: 'bold'}}
placeholder={'0'}
/>
</View>
)
}
}
i just start to learn react native i want to make ui like this,
i want the buttons on the image work like radio button, so user just can choose a button and change the button style choosed by user, and bellow is my code
class ButtonOption extends Component {
constructor(props) {
super(props);
this.state = {
data : [],
active : 0
};
}
loadButton(temp){
let result = [];
for (let i =0;i<temp.length;i++){
if(i==this.state.active){
result.push(
<View key={i} style={buttonOption.main}>
<TouchableOpacity style={buttonOption.tabActive} onPress={()=>{this.setState({active:i});alert(this.state.active)}}>
<Text style={buttonOption.labelActive}>{temp[i]}</Text>
</TouchableOpacity>
</View>)
}else{
result.push(
<View key={i} style={buttonOption.main}>
<TouchableOpacity style={buttonOption.tab} onPress={()=>{this.setState({active:i});alert(this.state.active)}}>
<Text style={buttonOption.label}>{temp[i]}</Text>
</TouchableOpacity>
</View>)
}
}
return result;
}
componentDidMount(){
this.setState({data:this.loadButton(this.props.arrButton)})
}
render() {
return (
<View style={{flexDirection:'row',padding:10}}>
{this.state.data}
</View>
);
}
}
export default ButtonOption;
on code above i was try to make button with looping, in looping function i use active as a state for check active button, and add function onPress so everytime user click button, active state will change, but when i run and choose button the active state won't change, what is wronge with my onPress code, can someone help please?
I think I might know the answer, You have generated the view using this.loadButton and saved it in this.state.data. This is done one time only. when the render method is called. It is expecting a new view based on states but this.state.data is not changing since you create it in componentDidMount. What you need to do is to call this.loadButton(this.props.arrButton) in render method. this will create new view every time render method is called.
render() {
return (
<View style={{flexDirection:'row',padding:10}}>
{this.loadButton(this.props.arrButton)}
</View>
);
}
This might do it, If you still have any error, please report.