Skip to content
This repository has been archived by the owner on Dec 31, 2020. It is now read-only.

Commit

Permalink
Move some more tracking internals into the tracking code
Browse files Browse the repository at this point in the history
  • Loading branch information
Royston-Shufflebotham-i2 committed Apr 27, 2019
1 parent c4c6bc6 commit 6c78e5b
Show file tree
Hide file tree
Showing 2 changed files with 28 additions and 21 deletions.
8 changes: 8 additions & 0 deletions src/reactionCleanupTracking.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,14 @@ export interface IReactionTracking {
changedBeforeMount?: boolean
}

export function createTrackingData(reaction: Reaction) {
const trackingData: IReactionTracking = {
cleanAt: Date.now() + CLEANUP_LEAKED_REACTIONS_AFTER_MILLIS,
reaction
}
return trackingData
}

/**
* The minimum time before we'll clean up a Reaction created in a render
* for a component that hasn't managed to run its effects. This needs to
Expand Down
41 changes: 20 additions & 21 deletions src/useObserver.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { Reaction } from "mobx"
import { useDebugValue, useEffect, useRef } from "react"
import { printDebugValue } from "./printDebugValue"
import {
CLEANUP_LEAKED_REACTIONS_AFTER_MILLIS,
createTrackingData,
IReactionTracking,
recordReactionAsCommitted,
scheduleCleanupOfReactionIfLeaked
Expand Down Expand Up @@ -42,27 +42,26 @@ export function useObserver<T>(
if (!reactionTrackingRef.current) {
// First render for this component (or first time since a previous
// reaction from an abandoned render was disposed).
const trackingData: IReactionTracking = {
cleanAt: Date.now() + CLEANUP_LEAKED_REACTIONS_AFTER_MILLIS,
reaction: new Reaction(observerComponentNameFor(baseComponentName), () => {
// Observable has changed, meaning we want to re-render
// BUT if we're a component that hasn't yet got to the useEffect()
// stage, we might be a component that _started_ to render, but
// got dropped, and we don't want to make state changes then.
// (It triggers warnings in StrictMode, for a start.)
if (trackingData.mounted) {
// We have reached useEffect(), so we're mounted, and can trigger an update
forceUpdate()
} else {
// We haven't yet reached useEffect(), so we'll need to trigger a re-render
// when (and if) useEffect() arrives. The easiest way to do that is just to
// drop our current reaction and allow useEffect() to recreate it.
trackingData.reaction.dispose()
reactionTrackingRef.current = null
}
})
}

const newReaction = new Reaction(observerComponentNameFor(baseComponentName), () => {
// Observable has changed, meaning we want to re-render
// BUT if we're a component that hasn't yet got to the useEffect()
// stage, we might be a component that _started_ to render, but
// got dropped, and we don't want to make state changes then.
// (It triggers warnings in StrictMode, for a start.)
if (trackingData.mounted) {
// We have reached useEffect(), so we're mounted, and can trigger an update
forceUpdate()
} else {
// We haven't yet reached useEffect(), so we'll need to trigger a re-render
// when (and if) useEffect() arrives. The easiest way to do that is just to
// drop our current reaction and allow useEffect() to recreate it.
newReaction.dispose()
reactionTrackingRef.current = null
}
})

const trackingData = createTrackingData(newReaction)
reactionTrackingRef.current = trackingData
scheduleCleanupOfReactionIfLeaked(reactionTrackingRef)
}
Expand Down

0 comments on commit 6c78e5b

Please sign in to comment.