反应本机获取 TextInput 值

我遇到了一个非常简单的问题。我有用户名,密码和按钮登录表单。在我的按钮处理程序中,我尝试获取文本输入值。但总是得到未定义的价值。我错过了什么吗?

render() {
<ExScreen
headerColor={this.state.headerColor}
scrollEnabled={this.state.enableScroll}
style={styles.container} >
<View >
<View  >
<View style={[styles.inputContainer]} >
<TextInput
ref= "username"
onChangeText={(text) => this.setState({text})}
value={this.state.username}
/>
</View>
<Button style={{color: 'white', marginTop: 30, borderWidth: 1, borderColor: 'white', marginLeft: 20*vw, marginRight: 20*vw, height: 40, padding: 10}}
onPress={this._handlePress.bind(this)}>
Sign In
</Button>
...
_handlePress(event) {
var username=this.refs.username.value;
197591 次浏览

Did you try

var username=this.state.username;

Please take care on how to use setState(). The correct form is

this.setState({
Key: Value,
});

And so I would do it as follows:

onChangeText={(event) => this.setState({username:event.nativeEvent.text})}
...
var username=this.state.username;

The quick and less optimized way to do this is by using arrow function inside your onChangeText callback, by passing username as your argument in your onChangeText callback.

<TextInput
ref= {(el) => { this.username = el; }}
onChangeText={(username) => this.setState({username})}
value={this.state.username}
/>

then in your _handlePress method

_handlePress(event) {
let username=this.state.username;
}

But this has several drawbacks!!!

  1. On every render of this component a new arrow function is created.
  2. If the child component is a PureComponent it will force re-renders unnecessarily, this causes huge performance issue especially when dealing with large lists, table, or component iterated over large numbers. More on this in React Docs

Best practice is to use a handler like handleInputChange and bind ```this`` in the constructor.

...
constructor(props) {
super(props);
this.handleChange= this.handleChange.bind(this);
}


...
handleChange(event = {}) {
const name = event.target && event.target.name;
const value = event.target && event.target.value;


this.setState([name]: value);
}
...


render() {
...
<TextInput
name="username"
onChangeText={this.handleChange}
value={this.state.username}
/>
...
}


...

Or if you are using es6 class property shorthand which autobinds this. But this has drawbacks, when it comes to testing and performance. Read More Here

...
handleChange= (event = {}) => {
const name = event.target && event.target.name;
const value = event.target && event.target.value;


this.setState([name]: value);
}
...


render() {
...
<TextInput
name="username"
onChangeText={this.handleChange}
value={this.state.username}
/>
...
}


...

This piece of code worked for me. What I was missing was I was not passing 'this' in button action:

 onPress={this._handlePress.bind(this)}>
--------------


_handlePress(event) {
console.log('Pressed!');


var username = this.state.username;
var password = this.state.password;


console.log(username);
console.log(password);
}


render() {
return (
<View style={styles.container}>


<TextInput
ref="usr"
style=\{\{height: 40, borderColor: 'gray', borderWidth: 1 , marginTop: 10 , padding : 10 , marginLeft : 5 , marginRight : 5 }}
placeHolder= "Enter username "
placeholderTextColor = '#a52a2a'


returnKeyType = {"next"}
autoFocus = {true}
autoCapitalize = "none"
autoCorrect = {false}
clearButtonMode = 'while-editing'
onChangeText={(text) => {
this.setState({username:text});
}}
onSubmitEditing={(event) => {
this.refs.psw.focus();


}}
/>


<TextInput
ref="psw"
style=\{\{height: 40, borderColor: 'gray', borderWidth: 1 , marginTop: 10,marginLeft : 5 , marginRight : 5}}
placeholder= "Enter password"
placeholderTextColor = '#a52a2a'
autoCapitalize = "none"
autoCorrect = {false}
returnKeyType = {'done'}
secureTextEntry = {true}
clearButtonMode = 'while-editing'
onChangeText={(text) => {
this.setState({password:text});
}}
/>


<Button
style=\{\{borderWidth: 1, borderColor: 'blue'}}
onPress={this._handlePress.bind(this)}>
Login
</Button>


</View>
);``
}
}

If you are like me and doesn't want to use or pollute state for one-off components here's what I did:

import React from "react";
import { Text, TextInput } from "react-native";
   

export default class Registration extends Component {
_register = () => {
const payload = {
firstName: this.firstName,
/* other values */
}
    

console.log(payload)
}
    

render() {
return (
<RegisterLayout>
<Text style={styles.welcome}>
Register
</Text>


<TextInput
placeholder="First Name"
onChangeText={(text) => this.firstName = text} />


{/*More components...*/}


<CustomButton
backgroundColor="steelblue"
handlePress={this._register}>
Submit
</CustomButton>
</RegisterLayout>
)
}
}

User in the init of class:

constructor() {
super()
this.state = {
email: ''
}
}

Then in some function:

handleSome = () => { console.log(this.state.email) };

And in the input:

<TextInput onChangeText={(email) => this.setState({email})}/>

In React Native 0.43: (Maybe later than 0.43 is OK.)

_handlePress(event) {
var username= this.refs.username._lastNativeText;

enter image description here

You should use States to store the value of input fields. https://facebook.github.io/react-native/docs/state.html

  • To update state values use setState

onChangeText={(value) => this.setState({username: value})}

  • and get input value like this

this.state.username

Sample code

export default class Login extends Component {
        

state = {
username: 'demo',
password: 'demo'
};
    

<Text style={Style.label}>User Name</Text>
<TextInput
style={Style.input}
placeholder="UserName"
onChangeText={(value) => this.setState({username: value})}
value={this.state.username}
/>
    

<Text style={Style.label}>Password</Text>
<TextInput
style={Style.input}
placeholder="Password"
onChangeText={(value) => this.setState({password: value})}
value={this.state.password}
/>


<Button
title="LOGIN"
onPress={() =>
{
if(this.state.username.localeCompare('demo')!=0){
ToastAndroid.show('Invalid UserName',ToastAndroid.SHORT);
return;
}


if(this.state.password.localeCompare('demo')!=0){
ToastAndroid.show('Invalid Password',ToastAndroid.SHORT);
return;
}


//Handle LOGIN


}
}
/>

If you set the text state, why not use that directly?

_handlePress(event) {
var username=this.state.text;

Of course the variable naming could be more descriptive than 'text' but your call.

export default class App extends Component {
state = { username: '', password: '' }


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}
/>
<TextInput
placeholder='Password'
onChangeText={val => this.onChangeText('password', val)}
style={styles.input}
secureTextEntry={true}
/>
</View>
);
}
}

Hope this will solve your problem

This work for me

    <Form>


<TextInput
style=\{\{height: 40}}
placeholder="userName"
onChangeText={(text) => this.userName = text}
/>


<TextInput
style=\{\{height: 40}}
placeholder="Password"
onChangeText={(text) => this.Password = text}
/>




<Button
title="Sign in!"
onPress={this._signInAsync}
/>


</Form>

and

  _signInAsync = async () => {
console.log(this.userName)
console.log(this.Password)
};

Every thing is OK for me by this procedure:

<Input onChangeText={this.inputOnChangeText} />

and also:

inputOnChangeText = (e) => {
this.setState({
username: e
})
}
constructor(props) {
super(props);


this.state ={
commentMsg: ''
}
}


onPress = () => {
alert("Hi " +this.state.commentMsg)
}


<View style={styles.sendCommentContainer}>


<TextInput
style={styles.textInput}
multiline={true}
onChangeText={(text) => this.setState({commentMsg: text})}
placeholder ='Comment'/>


<Button onPress={this.onPress}
title="OK!"
color="#841584"
/>


</TouchableOpacity>


</View>

Simply do it.

this.state={f_name:""};


textChangeHandler = async (key, val) => {
await this.setState({ [key]: val });
}


<Textfield onChangeText={val => this.textChangeHandler('f_name', val)}>

Try Console log the object and you will find your entered text inside nativeEvent.text

example:

handelOnChange = (enteredText) => {
console.log(enteredText.nativeEvent.text)
}
render()
return (
<SafeAreaView>
<TextInput
onChange={this.handelOnChange}
>
</SafeAreaView>


)

There is huge difference between onChange and onTextChange prop of <TextInput />. Don't be like me and use onTextChange which returns string and don't use onChange which returns full objects.

I feel dumb for spending like 1 hour figuring out where is my value.

React Native Latest -> Simple and easy solution using state based approach.

const [userEmail, setUserEmail] = useState("");


<TextInput
value={userEmail}
style={styles.textInputStyle}
placeholder="Email"
placeholderTextColor="steelblue"
onChangeText={(userEmail) => setUserEmail(userEmail)}
/>

You dont need to make a new function for taht. just make a new useState and use it in onchange.

const UselessTextInput = () => {
const [text, onChangeText] = React.useState("Useless Text");
const [number, onChangeNumber] = React.useState(null);


return (
<SafeAreaView>
<TextInput
style={styles.input}
onChangeText={onChangeText}
value={text}
/>
<TextInput
style={styles.input}
onChangeText={onChangeNumber}
value={number}
placeholder="useless placeholder"
keyboardType="numeric"
/>
</SafeAreaView>
);
};