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}
/>
CodePudding user response:
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.