Ensuring Child Component Reloads When Parent Component Changes

I am working on creating an updated implementation of an existing react native app and am running into a situation where a child component doesn’t re-load when the parent component changes.

My situation is this: I have a parent component for a particular record. Connected to this is a VisitTimer child component that keeps track of duration for a that record’s session. What I’m noticing is that, when I load a record into the parent component for the first time, the child component <VisitTimer> does fire with componentDidMount(). However, if exit that screen, and load a DIFFERENT record, then the child <VisitTimer> component does not mount – i.e. componentDidMount in the VisitTimer child component does not fire.

What is the likely issue here? And how can I ensure that a child component always re-mounts when the parent component changes?

Here is the child component within the parent:

  <VisitTimer
    started={this.props?.session?.dates?.started?.value}
    stopped={this.props?.session?.dates?.completed?.value}
    durationOverride={this.props?.session?.duration?.total?.value}
    maxDuration={maxVisitTime(this.props?.session?.type?.value)}
    visit={this.props?.session}
    ref={(ref) => (this.visitTimer = ref)}
    stopTimeOffset={this.props.visit?.duration?.stopOffset?.value}
    editable={statusCodeToEditableLevel(this.props.session?.status?.value) === 2}
    onChange={this.onSessionTimerChange}
  />

>Solution :

See my comments but a way to force this to be recreated is to give it a unique key based on the record. In react, key is special, and if it changes the whole component will remount. You could set the key to a unique id from the record:

  <VisitTimer
    key={this.props?.session?.guid}
    started={this.props?.session?.dates?.started?.value}
    stopped={this.props?.session?.dates?.completed?.value}
    durationOverride={this.props?.session?.duration?.total?.value}
    maxDuration={maxVisitTime(this.props?.session?.type?.value)}
    visit={this.props?.session}
    ref={(ref) => (this.visitTimer = ref)}
    stopTimeOffset={this.props.visit?.duration?.stopOffset?.value}
    editable={statusCodeToEditableLevel(this.props.session?.status?.value) === 2}
    onChange={this.onSessionTimerChange}
  />

I made an assumption the unique id is on session.guid.

By the way, this is generally a good idea over implementing componentDidUpdate in your situation. People often go that route and spend loads of time implementing reset behavior to set the state back to its original values, which is a source of bugs. Changing key guarantees you have a fresh start. The only time you shouldn’t do this to achieve a "reset" on a component is if remounting it and its children are expensive.

Leave a Reply