Hacktoberfest 2026 : les issues que les mainteneurs ont marquées pour octobre, ouvertes et accessibles aux débutants. Parcourir les issues Hacktoberfest

Fast Refresh doesn't reset the React Compiler memo cache from c()

Fermée Adaptée aux débutants
#69 0 commentaires 0 réactions 0 personnes assignées Voir sur GitHub

Les mainteneurs répondent en général sous 1 jour

Personne n'a encore pris cette issue.

Évaluation

Difficulté
2/5
Temps estimé
1-3 heures
Accessibilité débutants
82/100
Type d'issue
Bug
Clarté
Clairement spécifiée
Activité
Active
Stack technique
react, typescript
Domaine
frontend

Piste de recherche

Commencez par src/react/compiler-runtime.ts et examinez comment c() stocke son cache de mémoïsation ; comparez cela au traitement du refresh dans src/dom/dispatcher.ts. Ajoutez la reproduction à tests/fast-refresh.test.tsx et vérifiez que le composant mis à jour affiche after:1, puis after:2, tout en préservant l’état. L’issue indique que ce test et l’ensemble de la suite passent avec la modification suggérée.

Rédigé par le modèle d'indexation à partir du texte de l'issue.

Description

Summary

After a Fast Refresh update, components compiled by React Compiler keep rendering their old output. The compiler runtime's c() keeps its memo cache across the refresh, so cached JSX from the previous version of the component is returned until a full reload.

React resets this cache on refresh. In development, renderWithHooks sets ignorePreviousDependencies when the fiber's type changed, and useMemoCache then refills the cache with sentinels (ReactFiberHooks.js).

Reproduction

Added to tests/fast-refresh.test.tsx. The component is written the way the compiler emits it:

import { c } from 'react/compiler-runtime'

it('resets the React Compiler memo cache but preserves state', () => {
  function version(label: string) {
    return function Example() {
      const $ = c(3)
      const [count, setCount] = useState(0)
      let t0
      if ($[0] === Symbol.for('react.memo_cache_sentinel')) {
        t0 = () => setCount(n => n + 1)
        $[0] = t0
      } else t0 = $[0] as () => void
      let t1
      if ($[1] !== count) {
        t1 = <button onClick={t0}>{label}:{count}</button>
        $[1] = count
        $[2] = t1
      } else t1 = $[2]
      return t1
    }
  }
  const Before = version('before'), update = family(Before, 'stable')
  const { container } = setup(<Before />)
  click(container)
  update(version('after'))
  Refresh.performReactRefresh()
  expect(container.textContent).toBe('after:1')
  click(container)
  expect(container.textContent).toBe('after:2')
})

On main it fails with expected 'before:1' to be 'after:1'.

Cause

c() in src/react/compiler-runtime.ts stores the cache in a useRef, which survives the refresh. useMemo and useCallback already handle this case: depsEqual returns false while the fiber is refreshing.

Babel's compiler hides the bug in development because it also emits a source-hash check that clears the cache whenever the file changes. The Rust port in oxc-transform-react, which @vitejs/plugin-react uses for react({ compiler: true }), doesn't emit that check, so with it every hot update of a compiled component is stale.

Suggested fix

Back c() with useMemo, so it picks up the existing refresh handling in depsEqual:

export function c(size: number): Array<unknown> {
  return useMemo(() => new Array<unknown>(size).fill(MEMO_CACHE_SENTINEL), [size])
}

With this change the test above passes and the rest of the suite still passes (1860 passed, 91 skipped).

Versions
  • @tanstack/redact 0.2.0, and main at d56d87cb
  • react-refresh 0.19.0 (from the test suite)
  • oxc-transform-react 0.155.0 with @vitejs/plugin-react 6.1.2, where we first hit it

Disclaimer: this issue, including the reproduction test and the suggested fix, was researched and written by Claude, an AI assistant from Anthropic.

Langage dominant
TypeScript
Étoiles
408
Forks
13
Merge moyen
1 h 44 min
PR mergées (30 j)
21

Préparer son environnement

Ce projet ne fournit ni conteneur de développement, ni Dockerfile, ni guide de contribution : l'installation est à votre charge. Commencez par son README, et consultez notre guide de la première contribution pour les étapes générales.

Par où commencer

  1. Lisez l'issue en entier, puis le guide de contribution du projet.
  2. Signalez en commentaire que vous la prenez — cela évite que deux personnes fassent le même travail.
  3. Forkez le dépôt et travaillez sur une branche.
  4. Ouvrez une pull request qui référence le numéro de l'issue.

Autres issues de TanStack/redact

Toutes les issues de TanStack/redact

Issues similaires

Plus d'issues TypeScript

Recevez les nouvelles issues par e-mail

Un résumé court des issues GitHub adaptées aux débutants.