mirror of
https://github.com/facebook/react.git
synced 2025-11-01 09:12:30 +00:00
Ref validation allows passing refs as props
Updates ValidateNoRefAccessInRender to allow passing refs to JSX, but continue disallowing passing ref values (so `ref` is okay but not `ref.current`)
This commit is contained in:
+11
-3
@@ -49,10 +49,18 @@ export function validateNoRefAccessInRender(fn: HIRFunction): void {
|
||||
// for these instructions so they ensure we have a complete analysis.
|
||||
break;
|
||||
}
|
||||
case "JsxExpression": {
|
||||
// It's okay to pass refs to JSX, but not ref *values*
|
||||
for (const operand of eachInstructionValueOperand(instr.value)) {
|
||||
validateNonRefValue(error, operand);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case "FunctionExpression": {
|
||||
// For now we assume *all* function expressions are safe, eventually we can
|
||||
// be more precise and disallow ref access in functions that may be called
|
||||
// during render
|
||||
// functions are allowed to capture refs, so long as the function is not called
|
||||
// during render. see AnalyzeFunctions for how we ensure that functions which
|
||||
// capture refs get assigned a mutable range so we know here whether the function
|
||||
// is called or not
|
||||
const mutableRange = instr.lvalue.identifier.mutableRange;
|
||||
if (mutableRange.end > mutableRange.start + 1) {
|
||||
for (const operand of eachInstructionValueOperand(instr.value)) {
|
||||
|
||||
+32
@@ -0,0 +1,32 @@
|
||||
|
||||
## Input
|
||||
|
||||
```javascript
|
||||
function Component(props) {
|
||||
const ref = useRef(null);
|
||||
return <Foo ref={ref} />;
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
## Code
|
||||
|
||||
```javascript
|
||||
import { unstable_useMemoCache as useMemoCache } from "react";
|
||||
function Component(props) {
|
||||
const $ = useMemoCache(2);
|
||||
const ref = useRef(null);
|
||||
const c_0 = $[0] !== ref;
|
||||
let t0;
|
||||
if (c_0) {
|
||||
t0 = <Foo ref={ref} />;
|
||||
$[0] = ref;
|
||||
$[1] = t0;
|
||||
} else {
|
||||
t0 = $[1];
|
||||
}
|
||||
return t0;
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
+4
@@ -0,0 +1,4 @@
|
||||
function Component(props) {
|
||||
const ref = useRef(null);
|
||||
return <Foo ref={ref} />;
|
||||
}
|
||||
+19
@@ -0,0 +1,19 @@
|
||||
|
||||
## Input
|
||||
|
||||
```javascript
|
||||
function Component(props) {
|
||||
const ref = useRef(null);
|
||||
return <Foo ref={ref.current} />;
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
|
||||
## Error
|
||||
|
||||
```
|
||||
[ReactForget] InvalidInput: Ref values (the `current` property) may not be accessed during render. Cannot access ref value at freeze $20:TObject<BuiltInRefValue> (3:3)
|
||||
```
|
||||
|
||||
|
||||
+4
@@ -0,0 +1,4 @@
|
||||
function Component(props) {
|
||||
const ref = useRef(null);
|
||||
return <Foo ref={ref.current} />;
|
||||
}
|
||||
Reference in New Issue
Block a user