React Native:How to trigger TextInput instance blur in a method? - javascript

I click a button on the navigator, the current screen's one TextInput's is focus.
I need to set the TextInput's instance blur to trigger the textChange function to do something.
In my case, the cursor of TextInput is blinking all the time.
refs.username.blur() does not work.
My code :
class UploadRecordII extends Component{
static navigationOptions = ({ navigation, screenProps }) => ({
headerRight: (<Button containerStyle={{marginRight: 12,}} onPress={ UploadRecordII.onSubmit}>
<Text style={{color: 'white',fontSize: 18,}}>next</Text>
</Button>),
});
.....
static onSubmit() {
let that = UploadRecordII.instance;
debugger;
that.refs.username.blur();
debugger;
that.props.commitCreateRecordUpdate(that.refs.username._lastNativeText,that.imageList)
that.props.navigation.navigate('Record3');
}
...... in render(){
....
<TextInput ref = 'username' placeholder='' editable = {true} maxLength = {500}
keyboardType='default' multiline={true}
style={styles.input} underlineColorAndroid='rgba(0,0,0,0)'
onBlur={ ()=> this.textChange()}
clearButtonMode='always' placeholderTextColor='#D6D0D8'></TextInput>
...
}

refs don't work as strings anymore as expected. You need to define your ref e.g.
class UploadRecordII extends Component {
constructor(props) {
super(props);
this.usernameInput = null;
}
onSubmit() {
this.usernameInput.blur();
}
render() {
return (
<TextInput ref={(input) => this.usernameInput = input} ... />
)
}
}

Related

Render a new value into TextInput React Native

I've got a react native form with a button that should autofill some of the field based on some user's information. The point is that even if I update the state variable related to a TextInput, the TextInput does not display such data. Here's a short snippet for the sake of simplicity
export default class Component extends React.Component {
constructor(props) {
super(props);
this.state = {
value: null
}
}
autocompile = () => {
this.setState({"value": "new value"})
}
render() {
return (
<View>
<TouchableOpacity
onPress={() => {
this.autocompile
}}>
<Text>Autocompile</Text>
</TouchableOpacity>
<TextInput
onChangeText={(value) => this.setState({'value': value})}
value={this.state.value}
/>
</View>
)
}
}
}
Following this example, if I clicked "Autocompile", the TextInput below wouldn't show the new value, even though the state variable would be updated. My question is, how can I update a TextInput displayed value from the external without typing in?
Class Component Solution
import React from 'react';
import { Text, View, TextInput, TouchableOpacity } from 'react-native';
export default class Component extends React.Component {
constructor(props) {
super(props);
this.state = { value: '' };
this.autocompile = this.autocompile.bind(this);
}
autocompile() {
this.setState({ value: 'new value' });
}
render() {
return (
<View>
<TouchableOpacity onPress={this.autocompile}>
<Text>Autocompile</Text>
</TouchableOpacity>
<TextInput
onChangeText={(value) => this.setState({ value: value })}
value={this.state.value}
/>
</View>
);
}
}
Function Component Solution
import React, { useState } from 'react';
import { View, TouchableOpacity, Text, TextInput } from 'react-native';
const App = () => {
const [value, setValue] = useState('');
const autocompile = () => setValue('new value');
return (
<View>
<TouchableOpacity onPress={() => autocompile()}>
<Text>Autocompile</Text>
</TouchableOpacity>
<TextInput onChangeText={(value) => setValue(value)} value={value} />
</View>
);
};
export default App;
You need to change this
autocompile = () => {
this.setState({"value": "new value"})
}
to
autocompile = () => {
this.setState({ value: 'new value' })
}
and this one also
onChangeText={(value) => this.setState({'value': value})}
to
onChangeText={(value) => this.setState({ value })}

How do I read an already populated TextInput in React-Native?

I have a TextInput below :
Normally I am able to read TextInput when there is a change , the problem is the TextInput for password is populated with a default password .
So the user may not need to edit(change) it - therefore not triggering onChangeText method .
import React,{Component} from 'react'
import {View, Text, TextInput } from 'react-native'
export default class App extends Component {
constructor(props){
super(props);
this.state = {
username: '',
password: 12345
}
}
onChangeText = (key, val) => {
this.setState({ [key]: val})
}
render() {
return (
<View style={styles.container}>
<Text>Login Form</Text>
<TextInput
placeholder='Username'
onChangeText={val => this.onChangeText('username', val)}
style={styles.input}
value={this.state.username}
/>
<TextInput
placeholder='Password'
onChangeText={val => this.onChangeText('password', val)}
style={styles.input}
value={this.state.password}
secureTextEntry={true}
/>
</View>
);
}
}
Now , my question is how do I read TextInputs which are not being changed ?
change TextInput value prop to defaultValue. i think that might work. TextInput value prop does't allow to modify existing value.
<TextInput
placeholder='Password'
onChangeText={val => this.onChangeText('password', val)}
style={styles.input}
defaultValue={this.state.password}
secureTextEntry={true}
/>
There is a way to get TextInput value directly from the component via refs.
If the input receives text from value prop you can use _lastNativeText method as in the example below.
export default class App extends Component {
state = {
text: 'Hello!'
}
constructor(props) {
super(props);
this.inputRef = React.createRef();
}
componentDidMount() {
this.printTextInputValue();
}
printTextInputValue = () => {
const input = this.inputRef.current;
console.log(input._lastNativeText);
}
render() {
return (
<View style={styles.container}>
<TextInput value={this.state.text} ref={this.inputRef} />
<Button onPress={this.printTextInputValue} title="Get input value" />
</View>
);
}
}
If the TextInput uses defaultValue prop use _getText method to read the initial value.
export default class App extends Component {
constructor(props) {
super(props);
this.inputRef = React.createRef();
}
componentDidMount() {
this.printDefaultInputValue();
}
printDefaultInputValue = () => {
const input = this.inputRef.current;
console.log(input._getText());
}
printTextInputValue = () => {
const input = this.inputRef.current;
console.log(input._lastNativeText);
}
render() {
return (
<View style={styles.container}>
<TextInput defaultValue="Hello Default!" ref={this.inputRef} />
<Button onPress={this.printTextInputValue} title="Get input value" />
</View>
);
}
}
Do note however that these methods are not officially documented and may be removed in future versions of React Native, so use them at your own discretion.

"undefined is not an object" when trying to access TextInput of the sibling component using references

in Parent component, I'm trying to focus the TextInput of second Child component when submit button is pressed in the TextInput of the first Child component but this error comes up: error message
Child.js
import React from "react";
import { View, TextInput} from "react-native";
export default class Child extends React.Component {
focus = ref => {
ref.input.focus();
};
render() {
return (
<View>
<TextInput
placeholder='enter text'
onSubmitEditing={() => {
this.focus(this.props.destinationRef);
}}
ref={input => {
this.input = input;
}}
/>
</View>
);
}
}
Parent.js
import React from "react";
import Child from "./Child";
import { View, StyleSheet } from "react-native";
export default class Parent extends React.Component {
// componentDidMount() {
// setTimeout(() => {
// this.two.input.focus();
// }, 3000);
// }
render() {
return (
<View style={styles.container}>
<Child
destinationRef={() => {
if (!this.two) return this.two;
}}
ref={input => {
this.one = input;
}}
/>
<Child ref={input => (this.two = input)} />
</View>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: "#fff",
alignItems: "center",
justifyContent: "center"
}
});
Note that when I uncomment the componendDidMount, second TextInput successfully focuses three seconds after mounting.
I think the problem in render update. In first render time destinationRef is undefined, parent state not updated or force updated so props not updated too.
I try little bit optimize your code. You can use arrow function to bind this:
import React from "react";
import Child from "./Child";
import { View, StyleSheet } from "react-native";
export default class Parent extends React.Component {
_makeFocus(){
this.two.input.focus();
}
handleOnSubmit(){
this._makeFocus();
}
render() {
return (
<View style={styles.container}>
<Child
onSubmit={this.handleOnSubmit.bind(this)}
ref={input => {
this.one = input;
}}
/>
<Child ref={input => (this.two = input)} />
</View>
);
}
}
I would change the logic a little bit since I think the ref is giving you problems.
Parent:
<View style={styles.container}>
<Child next={this.two} ref={comp => this.one = comp}/>
<Child next={this.one} ref={comp => this.two = comp}/>
</View>
Child:
<TextInput
placeholder='enter text'
onSubmitEditing={() => {
if (this.props.next)
this.props.next.focus();
}}
/>
EDIT:
Your approach was correct I believe, I would just update the parent into this:
export default class Parent extends React.Component {
constructor(props){
super(props);
this.references = {};
}
onFocus = (ref) => {
this.references[ref].focus();
}
render() {
return (
<View style={styles.container}>
<Child
destinationRef={'two'}
onFocus={this.onFocus}
ref={input => this.references['one'] = input}
/>
<Child ref={input => this.references['two'] = input} />
</View>
);
}
}
and your child to:
export default class Child extends React.Component {
render() {
return (
<View>
<TextInput
placeholder='enter text'
onSubmitEditing={() => {
this.props.onFocus(this.props.destinationRef);
}}
/>
</View>
);
}
}

How to change parent's state from child component in react native?

I have a parent component App.js which looks like this
export default class App extends React.Component {
constructor(){
super();
this.state = {
registerusername: '',
}
}
Now I have a child component ChildComp.js which is a direct child of App.js and looks like this
class ChildComp extends React.Component {
render() {
return (
<View>
<TextInput
placeholder="Username"
placeholderTextColor = 'black'
onChangeText={(registerusername) => this.setState({registerusername})}
/>
<Text>
{this.state.registerusername.split(' ').map((word) => word && '🍕').join(' ')}
</Text>
</View>
}
}
I am attempting to change print the pizza logo just like the react native document under the TextInput field. I am having a hard time understanding how I can do this when the state, registerusername is in parent component and the ChildComp is stateless. I am doing `this.setState({registerusername})} in my ChildComp but I dont think it is referencing the parent's state.
in app'
setName = (name) => {
this.setState({ registerusername: name })
}
render() {
return (
<div>
<ChildComp registerusername={this.state.registerusername} setName={this.setName} />
</div>
)
}
in ChildComp
< TextInput
placeholder = "Username"
placeholderTextColor = 'black'
onChangeText = {(e) => this.props.setName(e.target.value)}
/>
< Text >
{ this.props.registerusername.split(' ').map((word) => word && '🍕').join(' ') }
</Text >

Give Custom props to TextInput and use it on event handlers

I'm new to react native and trying event handling and came up with a problem.
Suppose I have a code like this
class Demo extends React.Component {
constructor(props) {
this.textValues = {a: null, b: null};
}
handleChange(event) {
this.textValues['a'] = this.props.customProps;
this.textValues['b'] = event.nativeEvent.text;
}
render() {
return (
<View>
<TextInput
customProps = 'T1'
onChange = {this.handleChange.bind(this)}
/>
<TextInput
customProps = 'T2'
onChange = {this.handleChange.bind(this)}
/>
</View>
)
}
}
I want to access textValues from parent component i.e., Demo as well as customProps from TextInput but
If I bind this with handleChange then this refrence to Demo class and this.props.customProps gives undefined
If I do not bind this with handleChange then this.textValues is not defined and this.props.customProps gives perfect value
But I want to acess both textValues of Demo and customProps of TextInput in handleChange function.
class Demo extends React.Component {
constructor(props) {
super(props);
this.textValues = { a: null, b: null };
}
handleChange = field => (event) => {
console.log(field)
this.textValues[field] = event.nativeEvent.text
}
render() {
return (
<View>
<TextInput onChange={this.handleChange('a')} />
<TextInput onChange={this.handleChange('b')} />
</View>
)
}
}
ReactDOM.render(
<Demo />,
document.getElementById('container')
);
do you want the handleChange function to know which TextInput is called from?
try these codes
<TextInput
customProps = 'T1'
onChange = {(input)=>{
this.handleChange("T1", input)
}}
/>
<TextInput
customProps = 'T2'
onChange = = {(input)=>{
this.handleChange("T2", input)
}}
/>
and the hanleChange function is
handleChange(inputTag, inputText) {...}

Categories