sao
sao

Reputation: 1821

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;

Upvotes: 0

Views: 839

Answers (2)

Taki
Taki

Reputation: 17654

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"))

Upvotes: 1

Liam
Liam

Reputation: 6743

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>
    );
}
}

Upvotes: 1

Related Questions