How do I get the value in TextInput when onBlur is called? - react-native

In React Native, I want to pass the value of the TextInput in the onBlur event handler.
onBlur={(e) => this.validateText(e.target.value)}
e.target.value works for plain React. But, in react-native, e.target.value is undefined. What is the structure of event args available in React Native?

You should use the 'onEndEditing' method instead of the 'onBlur'
onEndEditing?: function Callback that is called when text input ends.
onBlur is a component function where onEndEditing is specific for TextInput
onEndEditing
This approach works for both multiline and single line.
<TextInput
onEndEditing={(e: any) =>
{
this.setState({textValue: e.nativeEvent.text})
}
}/>

In React Native, you can get the value of the TextInput from e.nativeEvent.text.
Unfortunately, this doesn't work for multiline={true}. One hack around this is to maintain a ref to your TextInput and access the text value through the _lastNativeText property of the component. For example (assuming you've assigned your TextInput component a ref of "textInput"):
onBlur={() => console.log(this.refs.textInput._lastNativeText)}

Simple solution:
This way onBlur your state's email will always have the last value changed by the user.
validate = () => {
const { email } = this.state
console.log('Validating Email Here!', email)
}
<TextInput
style={styles.input}
placeholder='E-mail'
onChangeText={email => this.setState({email})}
onBlur={e => this.validate()}
/>

Related

React Native textInput clear

I have a textinput like this:
<TextInput
secureTextEntry={true}
autoCompleteType="password"
onChangeText={val => setClave(val)}
/>
and the component is:
const [clave, setClave] = useState('');
which is just for the password, because it is a login screen.
So i press a button and execute some functions that validates the textInput data, and when is all ready, navigate to another screen,
my final function that navigates to another screen is this:
const goInicio = () => {
setClave('')
navigation.navigate('Home')
};
and what i tried to do there is to set the state of clave to an empty string but if i navigate back to the login screen the password will still be written, even though its value changed, and it no longer works to log in, it is still showing as if it has something written, how can i fix that?
The internal value state of TextInput and clave are unrelated since you have not set clave to be the value prop of TextInput. You are changing clave in the onChange method of the TextInput but not the other way around. This direction is one directional.
Instead, set the value prop of the TextInput to be equal to clave
<TextInput
value={clave}
secureTextEntry={true}
autoCompleteType="password"
onChangeText={val => setClave(val)}
/>

How to stop TextInput losing focus onChangeText?

I want to change the state of a parent component from a child's TextInput.
The problem is every time it changes the parent state the component re-renders, the TextInput is blurred and the keyboard disappears.
I tried keeping all the logic in the some component and changing the parent state without passing props. Now I've tried extracting the InputText container and putting it into a new file, changing the parents' state and receiving the value through the props, that's not working either.
Here is the text field component:
export default (ProfileTextInput = ({
placeholder,
label,
handleChange,
name,
value
}) => {
return (
<View style={styles.inputComponent}>
<Text style={styles.labelText}>{label.toUpperCase()}</Text>
<TextInput
key={Math.random()}
placeholder={placeholder || ""}
value={value}
onChangeText={val => handleChange(val, name)}
/>
</View>
);
});
and this is how it's being used:
const [newUserData, setNewUserData] = useState({ ...userData });
const changeHandler = (value, name) => {
setNewUserData({ ...newUserData, [name]: value });
};
return(
<ProfileTextInput
label="Username"
defaultValue={newUserData.username}
name="username"
value={newUserData.username}
handleChange={changeHandler}
/>
)
I expected it to continue letting me type like a normal TextInput, but it's only typing one letter and losing focus.
Try removing the defaultValue props from your components.
defaultValue is just the initial value passed to an uncontrolled component. Since you're setting the input value with a change handler, that makes your input a controlled component, and so you should just set the value explicitly.
Read these articles for more details on the differences between these cases:
React forms and controlled components
Uncontrolled components

Testing value change of TextInput in React Native with Jest

I have a TextInput component, which calls a custom function when its value changes through its onValueChange property.
Is it possible to simulate the change of the text of this TexInput with Jest, so that I test if that the custom function (which is passed as a prop) is called with correct parameters and produces correct results?
Yes its possible with jest and enzyme. Below is the definition of SearchBar component which receives a function as a prop. The function is called with the text typed.
const SearchBar = ({onSearch}) => {
return (
<View>
<TextInput
onChangeText={text => onSearch(text)}
/>
</View>
);
};
The testing can be carried as follows
const onSearch = jest.fn();
const wrapper = shallow(<SearchBar onSearch={onSearch} />);
wrapper.find('TextInput').simulate('changeText', 'test search text');
expect(onSearch).toHaveBeenCalledWith('test search text');

How to pass TextInput value from one screen to another in react native?

I know this question is already asked but i didn't find any proper solution. So here is my question, i want to pass TextInput value to another screen on submit button.So, please tell me How to pass the value and display on another screen. I am new in react native development.
At the top of your component you want to declare your state.
class App extends Component {
state = {text: ""};
Then you want to save whatever text is in your TextInput to that state.
<TextInput onChangeText={text => this.setState({text})} />
Then you would want to pass that state to the other component you would need it in.
Add this to the onPress of your submit button:
onPress={() => navigate('OtherComponent', { text: this.state.text} )}
Then in your "OtherComponent" you can access the state like this:
this.props.navigation.state.params.text
This is assuming that you are using react-navigation.
At the top of your component you want to declare your state.
class App extends Component {
state = {text: ""};
Then you want to save whatever text is in your TextInput to that state.
this.setState({text})} />
Then you would want to pass that state to the other component you would need it in.
Add this to the onPress of your submit button:
onPress={() => this.props.navigation.navigate('OtherComponent', { text: this.state.text} );
Then in your "OtherComponent" you can access the state like this:
this.props.navigation.state.params.text
This is assuming that you are using react-navigation.

React Native - Difference between onChange vs onChangeText of TextInput

I'm not sure when to use onChange vs onChangeText in a TextInput component. I know onChangeText accepts the changed text as an arg in the callback, but is that why you would use onChangeText, since you can then update state within the callback?
UPDATE 26.08.2019
Since the initial version of the answer, TextInput's API has changed, and answer below is no longer valid. I haven't worked with react-native for more than 2 years now, so I can't really tell which version had these changes.
Regarding the answer, onChangeText is still a simple prop, that gives whatever is the value of the input field on every change.
onChange on the other hand, passes an event with { nativeEvent: { eventCount, target, text} } (as mentioned in the comment to this answer). Now, I cannot tell with confidence, why do you need eventCount and target. I can only state, that eventCount is increased every time you interact with TextInput component (character added, removed, all deleted, value pasted) and target is a unique integer for that TextInput field. And text is the same value as in onChangeText
So basically, I would suggest to use onChangeText, as a more straight forward prop.
If you want to accomplish functionality like in the old answer(below), you can create custom component, that wraps TextInput and receives custom properties and passes them to the onChange prop later. Example below:
const MyTextInput = ({ value, name, type, onChange }) => {
return (
<TextInput
value={value}
onChangeText={text => onChange({ name, type, text })}
/>
);
};
And then use it whenever you need to use TextInput
handleChange(event) {
const {name, type, text} = event;
let processedData = text;
if(type==='text') {
processedData = value.toUpperCase();
} else if (type==='number') {
processedData = value * 2;
}
this.setState({[name]: processedData})
}
<MyTextInput name="username" type="text" value={this.state.username} onChange={this.handleChange}}>
<MyTextInput name="password" type="number" value={this.state.password} onChange={this.handleChange}}>
OLD ANSWER
onChangeText is basically a simplified version of onChange, so you can easily use it, without the hassle of going through event.target.value to get changed value.
So, when should you use onChange and when onChangeText?
If you have simple form with few textinputs, or simple logic, you can go straight away and use onChangeText
<TextInput value={this.state.name} onChangeText={(text) => this.setState({name: text})}>
If you have more complicated forms and/or you have more logic in handling data (like handling text differently from number) when user changes input, then you are better of with onChange, because it gives you more flexibility. For example:
handleChange(event) {
const {name, type, value} = event.nativeEvent;
let processedData = value;
if(type==='text') {
processedData = value.toUpperCase();
} else if (type==='number') {
processedData = value * 2;
}
this.setState({[name]: processedData})
}
<TextInput name="username" type="text" value={this.state.username} onChange={this.handleChange}}>
<TextInput name="password" type="number" value={this.state.password} onChange={this.handleChange}}>
Use it like this:
<Input label='First Name' onChange={this.onChange} value={this.state.first}/>
onChange = (event) => {
const {eventCount, target, text} = event.nativeEvent;
this.setState({first:text});
};
The target attribute seems useless. It doesn't look like you can attach data attributes to react-native elements and retrieve them from the target element like you can in react because the app is not a browser.
With react, we're told it's better practice to not attach inline functions to the onChange event for performance reasons. We're supposed to use custom props or data-* attributes on the HTML element and retrieve the information from e.target inside the onChange handler.
But with react-native it seems this format of passing data is actually acceptable:
<Input
label='First Name'
onChangeText={text=>this.onChange('first',text,'anotherValueIWantToPass')}
value={this.state.first}/>
onChangeText gives you just the string as the argument for the callback.
onChange gives you the synthetic event as the argument.