[compiler] Validate ref reads in render via improved impure value validation#35450
Closed
josephsavona wants to merge 2 commits intomainfrom
Closed
[compiler] Validate ref reads in render via improved impure value validation#35450josephsavona wants to merge 2 commits intomainfrom
josephsavona wants to merge 2 commits intomainfrom
Conversation
f64bb91 to
d8eb5fe
Compare
note: This implements the idea discussed in reactwg/react#389 (comment) Currently we create `Impure` effects for impure functions like `Date.now()` or `Math.random()`, and then throw if the effect is reachable during render. However, impurity is a property of the resulting value: if the value isn't accessed during render then it's okay: maybe you're console-logging the time while debugging (fine), or storing the impure value into a ref and only accessing it in an effect or event handler (totally ok). This PR updates to validate that impure values are not transitively consumed during render, building on the `Render` effect. The validation currently uses an algorithm very similar to that of InferReactivePlaces - building a set of known impure values, starting with `Impure` effects as the sources and then flowing outward via data flow and mutations. If a transitively impure value reaches a `Render` effect, it's an error. We record both the source of the impure value and where it gets rendered to make it easier to understand and fix errors: ``` Error: Cannot access impure value during render Calling an impure function can produce unstable results that update unpredictably when the component happens to re-render. (https://react.dev/reference/rules/components-and-hooks-must-be-pure#components-and-hooks-must-be-idempotent). error.invalid-impure-functions-in-render-via-render-helper.ts:10:25 8 | const array = makeArray(now); 9 | const hasDate = identity(array); > 10 | return <Bar hasDate={hasDate} />; | ^^^^^^^ Cannot access impure value during render 11 | }; 12 | return <Foo renderItem={renderItem} />; 13 | } error.invalid-impure-functions-in-render-via-render-helper.ts:6:14 4 | 5 | function Component() { > 6 | const now = Date.now(); | ^^^^^^^^^^ `Date.now` is an impure function. 7 | const renderItem = () => { 8 | const array = makeArray(now); 9 | const hasDate = identity(array); ``` Impure values are allowed to flow into refs, meaning that we now allow `useRef(Date.now())` or `useRef(localFunctionThatReturnsMathDotRandom())` which would have errored previously. The next PR reuses this improved impurity tracking to validate ref access in render as well.
…idation Updates to guard against *reading* refs during render via the improved validateNoImpureValuesInRender() pass. InferMutationAliasingEffects generates `Impure` effects for ref reads, and then this pass validates that those accesses don't flow into `Render` effects. We now call the impure value validation first so that it takes priority over validateNoRefAccessInRender - the latter still has all the existing logic for now, but we can dramatically simplify it in a follow-up PR so that it only has to validate against ref writes.
This was referenced Jan 16, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Updates to guard against reading refs during render via the improved validateNoImpureValuesInRender() pass. InferMutationAliasingEffects generates
Impureeffects for ref reads, and then this pass validates that those accesses don't flow intoRendereffects. We now call the impure value validation first so that it takes priority over validateNoRefAccessInRender - the latter still has all the existing logic for now, but we can dramatically simplify it in a follow-up PR so that it only has to validate against ref writes.Stack created with Sapling. Best reviewed with ReviewStack.