简体   繁体   中英

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} />

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM