Hacktoberfest 2026: die Issues, die Maintainer für den Oktober markiert haben – offen und einsteigerfreundlich. Hacktoberfest-Issues durchsuchen

varResolver: a var() resolved from the :root/inline/universal fallback isn't guarded — a token provided via context after first render never re-resolves

Offen
#377 1 Kommentar 0 Reaktionen 0 zugewiesene Personen Auf GitHub ansehen

Maintainer antworten meist innerhalb von 3 Tagen

@huytdps13400 arbeitet bereits daran.

Seit 03.10.2026.

  • #467 von @huytdps13400 — offen

Bewertung

Schwierigkeit
3/5
Geschätzter Aufwand
1-3 Stunden
Anfängerfreundlichkeit
25/100
Issue-Typ
Bug
Klarheit
Klar beschrieben
Aktivitätsstatus
Veraltet
Tech-Stack
react, react-native, typescript
Bereich
frontend, mobile

Rechercherichtung

Start in src/native/styles/variables.ts, in varResolver, and compare the name in variables branch, which pushes a guard, with the fallback path after variableHistory.add(name), which does not. Linked PR #467 is already open against this, so check it before writing anything. Done means a test where a var() resolves from :root, a VariableContextProvider then supplies the token, and the mounted node re-resolves.

Vom Indexierungsmodell aus dem Issue-Text verfasst.

Beschreibung

auto-triaged bug confirmed

Summary

In varResolver (src/native/styles/variables.ts), a re-render dependency guard is recorded only on the name in variables (inherited VariableContext) path. When a var() is instead resolved from the inline / universal / :root fallback, the function returns without pushing a guard. As a result, a token that is absent from context at first render (so it resolves from :root) and is later provided via a nearer VariableContextProvider is never re-resolved on an already-mounted node — the node stays at the :root/fallback value permanently.

It's timing-sensitive: it only manifests when the context value arrives after the first paint of the consuming node. On a fast first paint the token is already in context (guarded → works); on a slower first paint (e.g. Android/Hermes committing before an async provider updates) the node latches the fallback value forever.

Version

[email protected]

Repro

A styled/useCssElement node whose var(--x) starts unset (resolves from :root) and is later given a value via a VariableContextProvider higher in the tree keeps the :root value — it never re-resolves when --x subsequently appears in context.

Concretely: render a node using var(--brand) where --brand is not yet provided by any context; later push --brand into a VariableContextProvider. The mounted node keeps the :root/fallback value instead of updating.

Root cause

varResolver pushes renderGuards.push(["v", name, variables[name]]) inside the if (name in variables) { … } branch and then returns. The other path — reached when name is not in variables (it runs variableHistory.add(name) and then the inline → universal → :root → fallback lookups) — returns without recording any guard for name. So testGuards watches nothing for that token, and a later context change for it never triggers re-resolution of the mounted node.

Proposed fix

Record a guard for the "currently absent from context" state as well — push renderGuards.push(["v", name, variables[name]]) immediately after variableHistory.add(name) (before the fallback lookups). variables[name] is undefined there, which is the correct sentinel: the guard then fires precisely when the token later appears in context, and there is no value shadow (the returned value is still the :root/fallback until context provides one). It terminates cleanly — exactly one extra re-resolve on the absent→present transition.

Context

We hit this in a production React Native app where channel/brand CSS variables are supplied asynchronously (fetched, then injected as a delta over the :root defaults). iOS happened to paint after the fetch (token in context → guarded → correct); Android painted before it and latched the default. We're currently carrying a local patch that applies the one-line fix above; filing upstream so it can live in the library. Happy to open a PR if that's useful.

(Distinct from #245, which is about a memory leak on re-render.)

Vorherrschende Sprache
TypeScript
Sterne
166
Forks
45
Ø Merge
13 T. 14 Std.
Gemergte PRs (30 T.)
1

Entwicklungsumgebung

Erste Schritte

  1. Lesen Sie das ganze Issue und danach den Beitragsleitfaden des Projekts.
  2. Schreiben Sie ins Issue, dass Sie es übernehmen — das erspart doppelte Arbeit.
  3. Forken Sie das Repository und arbeiten Sie in einem Branch.
  4. Öffnen Sie einen Pull Request, der die Issue-Nummer nennt.

Mehr aus nativewind/react-native-css

Alle Issues in nativewind/react-native-css

Ähnliche Issues

Weitere Issues zu TypeScript

Neue Issues direkt in Ihr Postfach

Eine kurze Übersicht über anfängerfreundliche GitHub-Issues.