0

My Parent Component represents a form. The users filling in the form have access to information in the form that is updated in real time as they update certain fields. The Issue I am running into is. On one of these updates when we fetch the new data and pass it to the child randomly sometimes the child is receiving stale props. From the previous request. The structure is something like this.

export class Form extends React.Component<Props, State> {

  fetchUpdates = async (payload) => {
 
      this.setState({ isLoadingUpdates: true })
      await Service.getUpdates(payload)
        .then(response => {
          this.setState({ isLoadingUpdates: false, updates: response.data })
        })
        .catch(({ data: errors }) => this.setState({ isLoadingUpdates: false }))
    }
  }

  render () {
      const {
      updates,
      isLoadingUpdates,
    } = this.state


              <FormCombobox
                onChange={this.fetchUpdates}
                md={10}
                name="field"
                id="field"
                label="Field"
                onMenuOpen={() => forceCheck()}
                openMenuOnClick
                selectRef={this.itemSelect}
                value={values.item}
                options={itemOptions || []}
              />

    <Info
      data={updates}
      errorMessage={this.state.updatesError}
     />

  }

}

It doesn't occur every time but randomly either when the form is first updated or on one of the following updates the < Info > container recieves the previous requests response data. How can I stop the parent from passing stale data?

Haq.H
  • 863
  • 7
  • 20
  • 47
  • The code looks good. Some things to consider: **1.** if you are using `PureComponent` or `React.memo` you should make sure that `updates` it's always a new object (not a patched object). **2.** In your code you show: `this.state.updatesError` make sure that you are re-computing this when you get new data. Bonus-tip: since you are using await, it's easier to wrap in try/catch block. – pmoleri Sep 03 '20 at 19:01

1 Answers1

0

The problem here is that when fetchUpdates is called multiple times it gets out of order due to network delay. Let's say fetchUpdates is called three times, and let's say the request takes 5, 2 and 4 seconds respectively to complete. In this case, you can see that the second request calls setState before the first request. As a result, the info component gets passed the first value after the second value. This is the reason why it is intermittent.

Using await here won't help, because the fetchUpdates function calls are independent of each other.

One more thing, I noticed that you have isLoadingUpdates. But it's not being used anywhere in the code. And also doing,

if (!this.state. isLoadingUpdates) {
await Service.getUpdates(payload)
        .then(response => {
          this.setState({ isLoadingUpdates: false, updates: response.data })
        })
        .catch(({ data: errors }) => this.setState({ isLoadingUpdates: false }))
}

won't work because then it means you will miss keypresses when the network call is ongoing.

I would suggest using a debounce for the inputs. You can find how to do debounce here: Perform debounce in React.js

sidthesloth
  • 1,399
  • 1
  • 11
  • 19