Skip to content

Commit

Permalink
Fix up memoization of useTransition
Browse files Browse the repository at this point in the history
  • Loading branch information
brophdawg11 committed Dec 12, 2022
1 parent 1e5cacb commit 691c7c9
Show file tree
Hide file tree
Showing 3 changed files with 18 additions and 10 deletions.
1 change: 0 additions & 1 deletion integration/rendering-test.ts
Expand Up @@ -9,7 +9,6 @@ test.describe("rendering", () => {
let appFixture: AppFixture;

test.beforeAll(async () => {
process.env.NODE_ENV = "development";
fixture = await createFixture({
files: {
"app/root.jsx": js`
Expand Down
6 changes: 1 addition & 5 deletions integration/transition-state-test.ts
Expand Up @@ -32,11 +32,6 @@ test.describe("rendering", () => {
export default function() {
const transition = useTransition();
// TODO: This seems to have some issues with StrictMode?
// - Passes running only transition tests w/StrictMode
// - Passes on full suite with fullyParallel:false w/StrictMode
// - Fails on full suite with fullyParallel:true w/StrictMode
// - Passes on full suite with fullyParallel:true w/o StrictMode
const transitionsRef = useRef();
const transitions = useMemo(() => {
const savedTransitions = transitionsRef.current || [];
Expand All @@ -47,6 +42,7 @@ test.describe("rendering", () => {
return (
<html lang="en">
<head><title>Test</title></head>
<body>
<Outlet />
{transition.state != "idle" && (
Expand Down
21 changes: 17 additions & 4 deletions packages/remix-react/components.tsx
Expand Up @@ -796,6 +796,7 @@ import(${JSON.stringify(manifest.entry.module)});`;
/>
<script
{...props}
suppressHydrationWarning
dangerouslySetInnerHTML={createHtml(routeModulesScript)}
type="module"
async
Expand Down Expand Up @@ -957,10 +958,22 @@ export function useActionData<T = AppData>(): SerializeFrom<T> | undefined {
*/
export function useTransition(): Transition {
let navigation = useNavigation();
return React.useMemo(
() => convertNavigationToTransition(navigation),
[navigation]
);

// Have to avoid useMemo here to avoid introducing unstable transition object
// identities in StrictMode, since navigation will be stable but using
// [navigation] as the dependency array will _still_ re-run on concurrent
// renders, and that will create a new object identify for transition
let lastNavigationRef = React.useRef<Navigation>();
let lastTransitionRef = React.useRef<Transition>();

if (lastTransitionRef.current && lastNavigationRef.current === navigation) {
return lastTransitionRef.current;
}

lastNavigationRef.current = navigation;
lastTransitionRef.current = convertNavigationToTransition(navigation);

return lastTransitionRef.current;
}

function convertNavigationToTransition(navigation: Navigation): Transition {
Expand Down

0 comments on commit 691c7c9

Please sign in to comment.