jaimefps
jaimefps

Reputation: 2424

Update Redux after Component State change

Still learning to use Redux properly. I've been at this for an hour and need help. I want to update the state of a stateful component through its child functional component. Afterwards I want to activate a class method that uses a Redux action to update the store. I was trying to have these two things occur in order, but the state change is not accessible until the method that does it resolves.

How do I induce a redux action to activate once the local class state is updated?

My main issue is that the state updates AFTER handleMiniChange occurs, such that the full date in the Store is always one event behind in the history (i.e., I need to interact with the dropdowns twice in order for Redux to register the first action, and then it is always one step behind).

I tried this.forUpdate and this.componentWillUpdate but I ran into infinite loops.(Maybe I was doing it wrong...?)

Note that "update_field" is the redux action that takes care of updating the Store.

my code:

function MiniDropDown (props) {
  return (
      <select name={props.name} value={props.value} onChange={props.handleMiniChange}>
        {
          props.list.map((obj) => {
            return <option key={obj.Value} value={obj.Value}>{obj.Value}</option>
          })
        }
      </select>
    )
}

/*************************************************
 *                MAIN COMPONENT
*************************************************/

export default class DateMenu extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      month:'MM',
      day:'DD',
      year:'YYYY',
    }
    this.handleDateChange = this.handleDateChange.bind(this)
    this.handleMiniChange = this.handleMiniChange.bind(this)
  }

  handleMiniChange(event) {
    const name = event.target.name;
    const value = event.target.value;
    this.setState({ [name]: value});
    this.handleDateChange()
  }

  handleDateChange () {
    const _date = `${this.state.month}/${this.state.day}/${this.state.year}`;
    this.props.common_props.update_field(this.props.name, _date);
  }


  render() {

    const common_props= {
      form: this.props.common_props.form_data,
      handleMiniChange: this.handleMiniChange,
    }

    return (
      <div className='traveler_data_row'>
        <label> {this.props.specs.label} </label>

        <MiniDropDown value={this.state.month} 
                      name='month' 
                      list={getMonths()} 
                      {...common_props} />

        <MiniDropDown value={this.state.day}
                      name='day'
                      list={getDays()}
                      {...common_props} />

        <MiniDropDown value={this.state.year} 
                      name='year'
                      list={getYears()}
                      {...common_props} />
      </div>
    )
  }
}

Upvotes: 1

Views: 635

Answers (1)

Sagiv b.g
Sagiv b.g

Reputation: 31024

The problem here is that setState is an asynchronous operation.
That means after you call setState you can't be sure when exactly the state is realy updated and when you can use the new state in other handlers.
One solution is to use the setState callback function and invoke the second handler in the callback.

this.setState({ params }, this.secondHandler)

Upvotes: 2

Related Questions