Skip to content

Lifecycle with updates at multiple hierarchy levels #1210

Description

@william-vw

This seems to be a particular lifecycle that wasn't considered when making the componentWillReceiveProps function deprecated. Or, perhaps I just cannot find a built-in way in React on how to do this properly. In either case, some guidance would be highly appreciated.

In my project, a top-level component fetches data from a service and then passes it, when received, to lower-level components as props (i.e., the higher-level component is fully controlled). These lower-level components are fields that display the retrieved data, and allow adding and removing data items afterwards. Clearly, these operations need to be reflected in the state (and also sent to the restful service, but this is inconsequential here). Hence, it would make sense to make the state the "single source of truth" since the data could be updated by the lower-level component ("field" from now on) at any point, requiring a re-render each time (?)

When first creating the field (i.e., in the constructor), this data is not yet available, since it's fetched from the service. This means that a method such as componentWillReceiveProps or getDerivedStateFromProps should be used to derive the initial state from the props (?) Since componentWillReceiveProps is deprecated I recently tried replacing it with getDerivedStateFromProps. However, this function is called "on every render, regardless of the cause" (e.g., because of a state change), instead of componentWillReceiveProps "which only fires when the parent causes a re-render" (see here). Hence, any local state change (e.g., removing a data item) will also cause the getDerivedStateFromProps function to be called (including ones caused by getDerivedStateFromProps ...).

Currently, to differentiate between state & props updates, I introduced the following function, which only derives the state from the props once, and, after any local state change, will ignore changes in props. The function is called from the field's getDerivedStateFromProps function (ignoreFunction depends on the particular field, and returns whether state and props include the same data). Note that a local state change involves setting an update field to true in the state.

static getGroundStateFromProps(props, state, ignoreFn) {
    // nothing in state or props was updated
    if (ignoreFn(state, props))
      return null

`    // some relevant update occurred; either state or props
    else {
      // in case state has been updated once, consider it "ground truth"
      if (state.updated)
        return null
      else
        return { values: props.values }
    }
  }

Would this be a suitable pattern to deal with this issue?

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions