diff --git a/compiler/packages/babel-plugin-react-compiler/docs/passes/49-validateNoRefAccessInRender.md b/compiler/packages/babel-plugin-react-compiler/docs/passes/49-validateNoRefAccessInRender.md index 680f096937..f229048c7a 100644 --- a/compiler/packages/babel-plugin-react-compiler/docs/passes/49-validateNoRefAccessInRender.md +++ b/compiler/packages/babel-plugin-react-compiler/docs/passes/49-validateNoRefAccessInRender.md @@ -29,6 +29,12 @@ if (ref.current == null) { } ``` +This exception only applies to the ref access pattern itself. Other validations +still apply to the initializer expression. In particular, the initializer must +still be predictable during render. Impure calls such as `Date.now()` or +`Math.random()` continue to fail the `purity` rule even when they appear inside +an allowed null-guarded ref initialization. + Error messages produced: - Category: `Refs` - Reason: "Cannot access refs during render" diff --git a/compiler/packages/eslint-plugin-react-compiler/__tests__/ImpureFunctionCallsRule-test.ts b/compiler/packages/eslint-plugin-react-compiler/__tests__/ImpureFunctionCallsRule-test.ts index f89b049d10..9ca140edfa 100644 --- a/compiler/packages/eslint-plugin-react-compiler/__tests__/ImpureFunctionCallsRule-test.ts +++ b/compiler/packages/eslint-plugin-react-compiler/__tests__/ImpureFunctionCallsRule-test.ts @@ -34,6 +34,19 @@ testRule( makeTestCaseError('Cannot call impure function during render'), ], }, + { + name: 'Impure ref initialization still fails purity under a null guard', + code: normalizeIndent` + function Component() { + const ref = useRef(null); + if (ref.current === null) { + ref.current = Date.now(); + } + return
{ref.current}
; + } + `, + errors: [makeTestCaseError('Cannot call impure function during render')], + }, ], }, ); diff --git a/compiler/packages/eslint-plugin-react-compiler/__tests__/NoRefAccessInRender-tests.ts b/compiler/packages/eslint-plugin-react-compiler/__tests__/NoRefAccessInRender-tests.ts index 9953c8c213..46328abf83 100644 --- a/compiler/packages/eslint-plugin-react-compiler/__tests__/NoRefAccessInRender-tests.ts +++ b/compiler/packages/eslint-plugin-react-compiler/__tests__/NoRefAccessInRender-tests.ts @@ -16,7 +16,20 @@ testRule( 'no ref access in render rule', allRules[getRuleForCategory(ErrorCategory.Refs).name].rule, { - valid: [], + valid: [ + { + name: 'allow null-guarded ref initialization', + code: normalizeIndent` + function Component() { + const ref = useRef(null); + if (ref.current === null) { + ref.current = "stable"; + } + return
; + } + `, + }, + ], invalid: [ { name: 'validate against simple ref access in render',