-
Notifications
You must be signed in to change notification settings - Fork 47.6k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[compiler] Allow refs to be lazily initialized during render
Summary: The official guidance for useRef notes an exception to the rule that refs cannot be accessed during render: to avoid recreating the ref's contents, you can test that the ref is uninitialized and then initialize it using an if statement: ``` if (ref.current == null) { ref.current = SomeExpensiveOperation() } ``` The compiler didn't recognize this exception, however, leading to code that obeyed all the official guidance for refs being rejected by the compiler. This PR fixes that, by extending the ref validation machinery with an awareness of guard operations that allow lazy initialization. We now understand `== null` and similar operations, when applied to a ref and consumed by an if terminal, as marking the consequent of the if as a block in which the ref can be safely written to. In order to do so we need to create a notion of ref ids, which link different usages of the same ref via both the ref and the ref value. ghstack-source-id: d2729274f351e1eb0268f28f629fa4c2568ebc4d Pull Request resolved: #31188
- Loading branch information
Showing
19 changed files
with
628 additions
and
26 deletions.
There are no files selected for viewing
This file contains 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
42 changes: 42 additions & 0 deletions
42
...act-compiler/src/__tests__/fixtures/compiler/allow-ref-initialization.expect.md
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,42 @@ | ||
|
||
## Input | ||
|
||
```javascript | ||
//@flow | ||
import {useRef} from 'react'; | ||
|
||
component C() { | ||
const r = useRef(null); | ||
if (r.current == null) { | ||
r.current = 1; | ||
} | ||
} | ||
|
||
export const FIXTURE_ENTRYPOINT = { | ||
fn: C, | ||
params: [{}], | ||
}; | ||
|
||
``` | ||
|
||
## Code | ||
|
||
```javascript | ||
import { useRef } from "react"; | ||
|
||
function C() { | ||
const r = useRef(null); | ||
if (r.current == null) { | ||
r.current = 1; | ||
} | ||
} | ||
|
||
export const FIXTURE_ENTRYPOINT = { | ||
fn: C, | ||
params: [{}], | ||
}; | ||
|
||
``` | ||
### Eval output | ||
(kind: ok) |
Oops, something went wrong.