varResolver: a var() resolved from the :root/inline/universal fallback isn't guarded — a token provided via context after first render never re-resolves
维护者通常 3 天内回复
评估
- 难度
- 3/5
- 预计耗时
- 1-3 小时
- 新手友好度
- 25/100
- Issue 类型
- 缺陷
- 描述清晰度
- 描述清楚
- 活跃度
- 停滞
- 技术栈
- react, react-native, typescript
调研方向
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.
由索引模型根据 Issue 内容生成。
描述
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
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.)
- 主要语言
- TypeScript
- 星标
- 166
- 派生
- 45
- 平均合并
- 13 天 14 小时
- 30 天内合并 PR
- 1
环境准备
- 没有 Dockerfile 或 Docker Compose 文件
- 没有 Pull Request 模板
- 阅读贡献指南
从这里开始
- 先读完整个 Issue,再读项目的贡献指南。
- 在 Issue 下留言说明你要接手 —— 这能避免两个人做同样的事。
- Fork 仓库,在一个分支上完成修改。
- 提交 Pull Request,并在描述里引用这个 Issue 编号。
nativewind/react-native-css 的其他 Issue
-
难度 2/5 1-3 小时 新手友好度 78/100
nativewind/react-native-css#545 ·
维护者通常 3 天内回复
-
难度 2/5 1-3 小时 新手友好度 78/100
nativewind/react-native-css#544 ·
维护者通常 3 天内回复
-
难度 2/5 1-3 小时 新手友好度 78/100
nativewind/react-native-css#543 ·
维护者通常 3 天内回复
-
难度 2/5 1-3 小时 新手友好度 84/100
nativewind/react-native-css#540 ·
维护者通常 3 天内回复
-
难度 2/5 1-3 小时 新手友好度 78/100
nativewind/react-native-css#538 ·
维护者通常 3 天内回复
查看 nativewind/react-native-css 的全部 Issue
相似的 Issue
-
难度 2/5 1-3 小时 新手友好度 78/100
-
area:desktop area:ui bug platform:macos
难度 2/5 1-3 小时 新手友好度 67/100
anthropics/claude-code#106183 ·
维护者通常 1 天内回复
-
难度 2/5 1-3 小时 新手友好度 76/100
-
难度 1/5 1-3 小时 新手友好度 76/100
维护者通常 1 天内回复
-
reproduced
难度 2/5 1-3 小时 新手友好度 72/100
anomalyco/opencode#60558 · 1 条评论 ·
维护者通常 1 天内回复