skip to Main Content

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

2

Answers


  1. 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.

    Login or Signup to reply.
  2. Using a key will force a re-render but that’s not the primary purpose of key. React docs do talk about using the key like this but those are for specific use cases. In this case I would encourage to ask ourselves:

    • Do we really need to re-mount the child component or do we just want it to re-render
    • Regardless of the answer to the above question. Why do we need the child component to re-render. Is it because it needs to show an updated data?
    • If yes, then the child component should receive a prop from the parent or something from a global state which changes (in your case probably the record itself). That kind of prop change/state change will automatically trigger a re-render

    I hope this is helpful but the community can be even more helpful if you can share more details of your problem like – What does the parent component do, what does the child render, why do we want the child to re-render, etc

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search