How to reset State in React so the view updates - javascript

I am trying to reset a input field on state update. So when my state updates through a function my view would change as well. Below is my code:
constructor(props){
super(props)
this.state = { song: '',
videos: '' }
this.handleSongInput = this.handleSongInput.bind(this)
}
in my render function I do something like this
render () {
return (
<div>
<TextField
floatingLabelText="Search Songs"
value={this.state.value}
onChange={this.handleSongInput}
/>
<br />
<RaisedButton label="Search" onClick={this.searchSong} />
</div>
)
}
The handle function for the Input field is below. It is simply setting the state.
handleSongInput = (e) => {
this.setState({ song: e.target.value})
}
Now on button click I have the following function which resets the initial
searchSong = () => {
...
this.setState({song:''})
}
Now if I do a console.log I can see that the state has changed. But in my view I can still see that the text field is populated with previous text.
How can I set the value of textfield with current state

I believe you have a variable name issue:
value={this.state.value}
should read:
value={this.state.song}

Related

onChange handler for select not working - ReactJS

I have the following code where I am trying to update the value for the select tag.
constructor(props){
super(props)
this.state={value: 'Male'}
}
handleChange = (event) => {
this.setState({value: event.target.value})
this.props.selectCB(this.state.value)
console.log(this.state.value)
}
render(){
return (
<label>GENDER: <br/>
<select value={this.state.value} onChange={this.handleChange}>
<option value='Male'>Male</option>
<option value='Female'>Female</option>
<option value='Not Specified'>Not-Specified</option>
<option value='Non Binary'>Non-Binary</option>
</select>
<br/>
</label>
)
}
}
class NameForm extends React.Component{
constructor(props){
super(props)
this.state = {selectValue: ''}
}
handleSelectCallback = (selectData) => {
this.setState({selectValue: selectData})
}
handleSubmit = (event) => {
console.log('Logged select: ' + this.state.selectValue)
alert(`Submitted : ${this.state.selectValue}`)
event.preventDefault()
}
render(){
return <form onSubmit={this.handleSubmit}>
<SelectTag selectCB={this.handleSelectCallback}/>
<input type='submit' value='Submit'></input>
</form>
}
}
function App(){
return <NameForm/>
}
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(App());
The SelectTag is a child component to NameForm which in turn is rendered by the function App(). The change handler resides in SelectTag while the submit handler is in NameForm. I am trying to get the selected value from SelectTag to the parent NameForm by using a callback handleSelectCallback(). When the data in SelectTag is changed it is not being updated in NameForm.
If I start with the value Male and change it to Female, the value of selectValue in NameTag is still Male. If I change the value again (say to Not Specified), the value of selectValue changes to Female.
(Note: I noticed that this is working properly for other React components. I tested with components that render text boxes and text areas.)
You are sending the old state value through the callback. setState is async.
handleChange = (event) => {
// Schedule an update to the component with a new state value
this.setState({value: event.target.value})
// Callback with the outdated state value
this.props.selectCB(this.state.value)
}
You could just change it to the right value
handleChange = (event) => {
this.setState({value: event.target.value})
this.props.selectCB(event.target.value)
}
Or better yet, remove the state.value because it's not need. Instead keep the state in one place (the parent), and send the value and the callback down.
handleChange = (event) => {
this.props.selectCB(event.target.value)
}
// and
<select value={this.props.value} />
// and
<SelectTag selectCB={this.handleSelectCallback} value={this.state.selectValue} />

Cant get a text box state to refresh with user input, keeps going to default state despite using setState

I have a React file which displays a list of city data as a component. there is an input textbox above it which needs to accept user input. i am using state to display an initial string in the textbox, but i cannot get onChange to successfully use a function to setState. troubleshooting it with console.log i can see that when i attempt to change the state the function i am pointing to with onChange does work and changes one letter, but then the state snaps back to its default value. the problem seems to be with setState not saving the change and reverting back to the initial state after any changes are made. the text box content appears to not change at all, thought console.log shows a one letter change but then reverts back to the original state.
how do i update state? i want the user to be able to punch a number in and then compare it with the list.
import React, {Component} from 'react';
import Table from './Table';
import cities from './Cities';
class App extends Component {
state = {
userInput: "Your City Population"
}
popChanger = (event) => {
this.setState( {userInput: event.target.value} );
//console.log(event.target.value);
}
yourCity = (
<div>
<input
type='text'
onChange={this.popChanger}
value={this.state.userInput}
/>
</div>
)
render() {
return (
<div className = "App">
{this.yourCity}
<Table characterData = {cities} />
</div>
);
}
}
export default App;
setState() is saving your changes, just not in the right place,
popChanger() is an arrow function and updates the state of the App component,
yourCity has it's own this so it doesn't know about the App state.
you can either cahnge yourCity to an arrow function that returns the html you want like
class TodoApp extends React.Component {
state = {
a: ''
};
YourCity = () => (
<div>
<input type="text" onChange={this.handleChange} value={this.state.a} />
</div>
}
handleChange = e => this.setState({a : e.target.value})
render() {
return (
<div>
<this.YourCity />
</div>
)
}
}
ReactDOM.render(<TodoApp />, document.querySelector("#app"))
Or, create yourCity component outside and pass the handleChange as a prop :
const YourCity = props => (
<div>
<input type="text" onChange={props.handleChange} value={props.value} />
</div>
)
class TodoApp extends React.Component {
state = {
a: ''
};
handleChange = e => this.setState({a : e.target.value})
render() {
return (
<div>
<YourCity handleChange={this.handleChange} value={this.state.a}/>
</div>
)
}
}
ReactDOM.render(<TodoApp />, document.querySelector("#app"))
The state is updating but you can't see that because this.yourCity doesn't re-render
popChanger = (event) => {
this.setState( {userInput: event.target.value} );
console.log(event.target.value);
}
yourCity(){
return <div>
<input
type='text'
onChange={this.popChanger}
value={this.state.userInput}
/>
</div>
}
render() {
return (
<div className = "App">
{this.yourCity()}
</div>
);
}
}

ReactJS : Form Data Capture : values not setting properly

I am trying out with a small react app, with a form based data capture, after keying in the values, when user clicks submit button, values need to be captured in state variable. But, state variable contains null value in handleSubmit function. For clarity, code snippets are given below,
Constructor code, for the sake of completeness/clarity,
constructor(props)
{
super(props);
this.state = {
username : '',
};
}
handleChange function is where I set state variable,
handleChange = (event) => {
this.setState( [event.target.username]: event.target.value );
}
handleSubmit function is where, I print state variable, which contains null value, instead of user inputted value.
handleSubmit = () => {
console.log(this.state.username);
}
Component's render function is given below, which invokes handleChange
and handleSubmit.
render() {
return(
<div>
<form>
<label>
Title:
<input
type = "text"
name="username"
onChange={event => this.handleChange(event)}/>
</label>
<button
label="Submit"
onClick={this.handleSubmit}>
Submit
</button>
</form>
</div>
)};
I am missing on something. I am new to react. Kindly advise.
you need setState's argument to be an object.
handleChange = (event) => {
this.setState({ [event.target.username]: event.target.value });
}

Component won't rerender after setState

I recently got started with React and want to build a little application to fetch weather data. My API has a function to return autocomplete suggestions. So when my autosuggestion array is not empty I render a list and upon clicking one of the <li>'s I want the value inside of the input box. I manage to set the state of my SearchBar but can't change it's value.
Edit: I try to get my value from changeState() into my <input type="text" placeholder="City, Zip Code, Coordinates" onChange={evt => this.updateInputValue(evt)} />. I can search for terms otherwise.
import React from 'react';
import './SearchBar.css';
import Suggestion from './Suggestion';
class SearchBar extends React.Component{
constructor(props) {
super(props);
this.state = {inputValue: ''};
this.search = this.search.bind(this);
this.updateInputValue = this.updateInputValue.bind(this);
this.handleKeyPress = this.handleKeyPress.bind(this);
this.changeState = this.changeState.bind(this);
}
changeState(value) {
console.log(value);
// Logs value of text between <li></li>
this.setState({inputValue: value});
}
search() {
this.props.onSearch(this.state.inputValue);
}
updateInputValue(evt) {
this.setState({
inputValue: evt.target.value
});
this.props.onChange(this.state.inputValue);
}
handleKeyPress(e) {
if(e.key === 'Enter') {
this.search();
}
}
render() {
return (
<div>
<div className="SearchGroup" onKeyPress={this.handleKeyPress} >
<input type="text" placeholder="City, Zip Code, Coordinates" onChange={evt => this.updateInputValue(evt)} />
<a onClick={this.search}>Go</a>
</div>
<Suggestion autocomplete={this.props.autocomplete} onSelect={this.changeState} />
</div>
);
}
}
export default SearchBar;
For the sake of completeness my Suggestion.js:
import React from 'react';
import './Suggestion.css';
class Suggestion extends React.Component{
constructor(props) {
super(props);
this.updateInputField = this.updateInputField.bind(this);
}
updateInputField(evt) {
this.props.onSelect(evt.currentTarget.innerText);
}
render(){
if(this.props.autocomplete && this.props.autocomplete.length > 0) {
return (
<div className="Suggestion">
<ul>
{
this.props.autocomplete.map((location) => {
return (
<li key={location.id} onClick={this.updateInputField}>{location.name}</li>
)
})
}
</ul>
</div>
);
} else {
return <div className="None"></div>
}
}
}
export default Suggestion;
I would also prefer to submit location.url in Suggestion, but I could not find a property that matches inside of evt.
As mentioned in my comment. You are setting state and immediately passing state to onChange function in updateInputValue event handler function which is not correct. Because you won't get the state value updated immediately, the state value updates only when it renders so, pass evt.target.value directly like below
updateInputValue(evt) {
this.setState({ inputValue: evt.target.value });
this.props.onChange(evt.target.value);
}
In order to see chnaged value on your input field, you have to pass value prop to input tag like below
<input type="text" placeholder="City, Zip Code, Coordinates" onChange={evt => this.updateInputValue(evt)} value={this.state.inputValue}/>
I would guess that you are trying to use value from state that isnt there yet, because setState is asynchronous
so either use callback on setState
updateInputValue(evt) {
this.setState({
inputValue: evt.target.value
}, ()=> this.props.onChange(this.state.inputValue));
}
or, use the value from event directly
updateInputValue(evt) {
const value = evt.target.value
this.setState({
inputValue: value
});
this.props.onChange(value)
}
plus you havent assigned value back to your input:
<input type="text" placeholder="City, Zip Code, Coordinates" onChange={evt => this.updateInputValue(evt)} value={this.state.inputValue}/>
The React setState doesn't update the state immediately. It puts it in the queue and updates the state in batches. if you want to access the updated state write the code in the setState callBack
this.setState({ inputValue: evt.target.value},()=> this.props.onChange(this.state.inputValue));
something like this

How to dynamically set State from Form input

I have 2 React parent/child components. The Child Component has a button that adds +1 to the previous state of the Parent Component, and a Form that triggers a handleChange function for the onChange event.
The Problem
From the Form input, I want to trigger a function that sets the State to the previous State, + the input in the Form.
For example, if I write 50 in input and hit submit I want the new state be 100
Here is a codesandbox: https://codesandbox.io/s/30mz2vvyo1
class Parent extends React.Component {
constructor(props) {
super(props);
this.state = {
value: 50
}
this.handleChange = this.handleChange.bind(this);
this.handleSubmit = this.handleSubmit.bind(this);
}
handleChange(event) {
this.setState((prevState) => {
return { value: prevState.value + 1 }
});
}
handleSubmit(event) {
event.preventDefault();
}
render() {
return (
<div>
<Child value={this.state.value} handleChange={this.handleChange} handleSubmit={this.handleSubmit} />
</div>
)
}
}
class Child extends React.Component {
render() {
return (
<div>
<button onClick={this.props.handleChange}>Count + 1</button>
<div>{this.props.value}</div>
<form onSubmit={this.props.handleSubmit}>
<label>
Name:
<input type="text" onChange={this.props.handleChange} />
</label>
<input type="submit" value="Submit" />
</form>
</div>
)
}
}
The problem you are facing can be mitigated by;
You need to have two different variables in state. value, can hold your value. You also need to hold the current value of the input, let's call it inputNumber.
You need to provide an onClick function to your button. In said function, set your state in the following fashion;
Code:
this.setState({
value: this.state.value + this.state.inputNumber,
})
After doing these things, it should work as expected.
I have updated your codesandbox, you can take a look at it here.

Categories