Reputation: 8619
This is my render function:
render: function() {
return <div className="input-group search-box">
<input
onChange={this.handleTextChange}
type="text"
value={this.state.text}
className="form-control search-item" />
<span className="input-group-btn"></span>
</div>
}
and I have this as my event handler:
handleTextChange: function(event) {
console.log(event.target.value);
this.setState({
text: event.target.value
});
}
The problem is that when I "save" an item, or console.log print the output, the last character is missing - for instance, if I enter "first", I'll get "firs" printed out, and there needs to be another key event to capture the last character. I've tried onKeyUp
- which doesn't let me type anything in, and I've also tried onKeyDown
and onKeyPress
, which output nothing.
What is happening here and why? and how can I get that last character to show up?
Upvotes: 78
Views: 58193
Reputation: 1
You are printing to the console before setting the state. Write your console log after the state is set. It will show the full text. (I had the same problem)
handleTextChange: function(event) {
**console.log(event.target.value)**
this.setState({
text: event.target.value
});
}
Upvotes: 0
Reputation: 161
import React, { useState, useEffect } from 'react';
const MyComponent = () => {
const [userInput, setUserInput] = useState("");
const changeHandler = (e) => {
setUserInput(e.target.value);
}
useEffect(()=> {
//here you will have correct value in userInput
},[userInput])
return (
<div>
<input onChange={changeHandler} value={userInput}></input>
</div>
)
}
Upvotes: 9
Reputation: 156
Since React v.16.8 react hooks can be helpful. I would recommend useState AND useEffect. The Example is in React Native, however it should show how to work with the useEffect. More information about useEffect: https://reactjs.org/docs/hooks-effect.html
import React, {useState, useEffect} from 'react';
import { TextInput } from 'react-native';
export interface Props{}
const InformationInputs: React.FC<Props> = (props) => {
const [textInputs, setTextInputs] = useState("");
const handleValueChange = () => {
console.log(textInputs);
}
useEffect(() => {
handleValueChange();
}, [textInputs]);
return (
<TextInput
placeholder={'Text'}
onChangeText={(value: string) => { setTextInputs(value) }}
/>
);
};
Upvotes: 7
Reputation: 1
Since React v. 16.8 you can use react hooks.
import React, { useState } from 'react';
const MyComponent = () => {
const [userInput, setUserInput] = useState("");
const changeHandler = (e) => {
setUserInput(e.target.value);
}
return (
<div>
<input onChange={changeHandler} value={userInput}></input>
</div>
)
}
It works great for me.
Upvotes: -2
Reputation: 339
Since setState() function in asynchronous, I used await.I achieved this using async and await, here is my code
render: function() {
return <div className="input-group search-box">
<input
onChange={(e) => {this.handleTextChange(e)}}
type="text"
value={this.state.text}
className="form-control search-item" />
<span className="input-group-btn"></span>
</div>
}
The handleTextCahnge function:
handleTextChange = async function(event) {
await this.setState({text: event.target.value});
console.log(this.state.text);
}
Upvotes: 10
Reputation: 5414
setState() function in asynchronous. Without using callback you can use another auxiliary variable to store and use the updated value immediately. Like :
export default class My_class extends Component{
constructor(props)
{
super(props):
this.state={
text:"",
};
this.text="";
}
render: function() {
return <div className="input-group search-box">
<input
onChange={this.handleTextChange}
type="text"
value={this.state.text}
className="form-control search-item" />
<span className="input-group-btn"></span>
</div>
}
handleTextChange: function(event) {
console.log(event.target.value);
this.text = event.target.value;
this.setState({
text: event.target.value
});
}
You will get your updated value in this.text variable immediately. But you should use this.state.text to show text in your UI.
Upvotes: 2
Reputation: 159095
When are you logging the state? Remember that setState
is asynchronous, so if you want to print the new state, you have to use the callback parameter. Imagine this component:
let Comp = React.createClass({
getInitialState() {
return { text: "abc" };
},
render() {
return (
<div>
<input type="text" value={this.state.text}
onChange={this.handleChange} />
<button onClick={this.printValue}>Print Value</button>
</div>
);
},
handleChange(event) {
console.log("Value from event:", event.target.value);
this.setState({
text: event.target.value
}, () => {
console.log("New state in ASYNC callback:", this.state.text);
});
console.log("New state DIRECTLY after setState:", this.state.text);
},
printValue() {
console.log("Current value:", this.state.text);
}
});
Typing a d
at the end of the input will result in the following being logged to the console:
Value from event: abcd
New state DIRECTLY after setState: abc
New state in ASYNC callback: abcd
Notice that the middle value is missing the last character. Here's a working example.
Upvotes: 71