From d9013067d83fb1499ded072be8538329074b238c Mon Sep 17 00:00:00 2001 From: Ayc0 Date: Wed, 13 Dec 2023 00:12:28 +0000 Subject: [PATCH 01/10] RFC: auto apply useIsolation via the compiler --- text/0000-automate-use-isolation.md | 97 +++++++++++++++++++++++++++++ 1 file changed, 97 insertions(+) create mode 100644 text/0000-automate-use-isolation.md diff --git a/text/0000-automate-use-isolation.md b/text/0000-automate-use-isolation.md new file mode 100644 index 00000000..157c058f --- /dev/null +++ b/text/0000-automate-use-isolation.md @@ -0,0 +1,97 @@ +- Start Date: 2024-11-18 +- RFC PR: https://github.com/reactjs/rfcs/pull/260 +- React Issue: (leave this empty) + +# Summary + +This RFC proposes to automatically apply `useIsolation(() => …)` (see https://github.com/reactjs/rfcs/pull/257) to all custom hooks using the [React compiler](https://react.dev/learn/react-compiler). + +# Basic example + +Let’s say someone write this custom hook in their code: + +```jsx +function useLongPoll(url, delay) { + const [id, setId] = React.useState(0); + + React.useEffect(() => { + const intervalId = setInterval(() => setId((id) => id + 1), delay); + return () => clearInterval(intervalId); + }, [delay]); + + const [status, setStatus] = React.useState(); + React.useEffect(() => { + const controller = new AbortController(); + fetchStatus(url, { signal: controller.signal }).then((result) => + setStatus(result) + ); + return () => controller.abort(); + // Trigger a re-fetch every so often + }, [id]); + + return status; +} +``` + +The React compiler could automatically _patch_ it to look like the following: + +```jsx +function useLongPoll(url, delay) { + return useIsolation(() => _useLongPoll(url, delay), [url, delay]); +} + +function _useLongPoll(url, delay) { + const [id, setId] = React.useState(0); + + React.useEffect(() => { + const intervalId = setInterval(() => setId((id) => id + 1), delay); + return () => clearInterval(intervalId); + }, [delay]); + + const [status, setStatus] = React.useState(); + React.useEffect(() => { + const controller = new AbortController(); + fetchStatus(url, { signal: controller.signal }).then((result) => + setStatus(result) + ); + return () => controller.abort(); + // Trigger a re-fetch every so often + }, [id]); + + return status; +} +``` + +# Motivation + +This topic is mostly for performance reasons, see [comment in the original RFC](https://github.com/Ayc0/react-rfcs/blob/main/text/0000-use-isolation.md#wrapping-existing-hooks-for-perf-optimizations-only). + +One of the main problem when creating custom hooks / calling custom from 3rd party libraries, is that they can depend on their own update cycles, and they can create a lot of renders that may not be used in the end to drive UI changes. `useIsolation` introduced in another RFC can fix that, but developers still have to manually apply it when needed. + +With the introduction of the React compiler, the compiler automatically applies the equivalent of `useMemo`, it seems fitting to also extend it to `useIsolation`. + +# Detailed design + +TO FILL + +# Drawbacks + +If the written code properly follows the rule of hooks, no code should depend on render cycles. So automatically applying `useIsolation()` should be fine. + +For the code paths not strictly following them, we can follow the current behavior of the compiler: not doing anything. + +# Alternatives + +TO FILL + +# Adoption strategy + +TO FILL + +# How we teach this + +TO FILL + +# Unresolved questions + +TO FILL From 0d93d79cc6b6743899d431b698e95a7ac0af5f58 Mon Sep 17 00:00:00 2001 From: Ayc0 Date: Mon, 18 Nov 2024 13:25:21 +0100 Subject: [PATCH 02/10] Update PR # --- text/0000-automate-use-isolation.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/text/0000-automate-use-isolation.md b/text/0000-automate-use-isolation.md index 157c058f..0d897a0e 100644 --- a/text/0000-automate-use-isolation.md +++ b/text/0000-automate-use-isolation.md @@ -1,5 +1,5 @@ - Start Date: 2024-11-18 -- RFC PR: https://github.com/reactjs/rfcs/pull/260 +- RFC PR: https://github.com/reactjs/rfcs/pull/261 - React Issue: (leave this empty) # Summary From 8988b60043cd2ef62dae41e3ca140bc18ea55866 Mon Sep 17 00:00:00 2001 From: Benjamin Koltes Date: Sat, 30 Nov 2024 22:02:15 +0100 Subject: [PATCH 03/10] Update 0000-automate-use-isolation.md --- text/0000-automate-use-isolation.md | 105 +++++++++++++++++++++++++--- 1 file changed, 95 insertions(+), 10 deletions(-) diff --git a/text/0000-automate-use-isolation.md b/text/0000-automate-use-isolation.md index 0d897a0e..a30af3c0 100644 --- a/text/0000-automate-use-isolation.md +++ b/text/0000-automate-use-isolation.md @@ -11,6 +11,12 @@ This RFC proposes to automatically apply `useIsolation(() => …)` (see https:// Let’s say someone write this custom hook in their code: ```jsx +function App() { + const status = useLongPoll('/url', 100); +} + +// ... + function useLongPoll(url, delay) { const [id, setId] = React.useState(0); @@ -36,11 +42,13 @@ function useLongPoll(url, delay) { The React compiler could automatically _patch_ it to look like the following: ```jsx -function useLongPoll(url, delay) { - return useIsolation(() => _useLongPoll(url, delay), [url, delay]); +function App() { + const status = useIsolation(() => useLongPoll('/url', 100), []); } -function _useLongPoll(url, delay) { +// ... + +function useLongPoll(url, delay) { const [id, setId] = React.useState(0); React.useEffect(() => { @@ -68,30 +76,107 @@ This topic is mostly for performance reasons, see [comment in the original RFC]( One of the main problem when creating custom hooks / calling custom from 3rd party libraries, is that they can depend on their own update cycles, and they can create a lot of renders that may not be used in the end to drive UI changes. `useIsolation` introduced in another RFC can fix that, but developers still have to manually apply it when needed. -With the introduction of the React compiler, the compiler automatically applies the equivalent of `useMemo`, it seems fitting to also extend it to `useIsolation`. +With the introduction of the React compiler, the compiler automatically applies the equivalent of `useMemo`, it seems fitting to also extend it to `useIsolation` (also as the React team planned to potentially extend `useMemo` to work exactly like this `useIsolation`, it was previously mentioned on Twitter, but I have no link to add here as those tweets have been deleted since). # Detailed design -TO FILL +We can use the same rule used in the React compiler that automatically wraps variables in `useMemo`, to detect when custom hooks are getting called (check their names match `/use[A-Z].*/`), and automatically wraps them in `useIsolation`. We can also use the same rule to check which variables to add in the dependencies array, or fallback to `[]` if no external variable is used. + +> [!note] +> As mentioned in https://github.com/reactjs/rfcs/pull/257, the dependency array is not required for `useIsolation` to work. But this will allow fully skipping the call the hook if nothing changed, skipping a few checks (one for each hook used in those, no need to perform `useState` resolution, or cache checks for `useMemo` / `useCallback`, etc.). +> So this would still be a win: 1 cache check to avoid a lot # Drawbacks If the written code properly follows the rule of hooks, no code should depend on render cycles. So automatically applying `useIsolation()` should be fine. - For the code paths not strictly following them, we can follow the current behavior of the compiler: not doing anything. +Also, this would add 1 `useIsolation` call in all component, adding an extra cache check for each component, which can make the memory usage higher, and potentially slow down (at least on initial mounts, and/or on non-properly memoized architecture). + # Alternatives -TO FILL +Instead of wrapping the call sites like proposed, potentially we could wrap the hooks at their definitions, like so: + +```jsx +function App() { + const status = useLongPoll('/url', 100); +} + +// ... + +function useLongPoll(url, delay) { + const [id, setId] = React.useState(0); + + React.useEffect(() => { + const intervalId = setInterval(() => setId((id) => id + 1), delay); + return () => clearInterval(intervalId); + }, [delay]); + + const [status, setStatus] = React.useState(); + React.useEffect(() => { + const controller = new AbortController(); + fetchStatus(url, { signal: controller.signal }).then((result) => + setStatus(result) + ); + return () => controller.abort(); + // Trigger a re-fetch every so often + }, [id]); + + return status; +} +``` + +becoming + +```jsx +function App() { + const status = useLongPoll('/url', 100); +} + +// ... + +function useLongPoll(url, delay) { + return useIsolation(() => _useLongPoll(url, delay), [url, delay]); +} + +function _useLongPoll(url, delay) { + const [id, setId] = React.useState(0); + + React.useEffect(() => { + const intervalId = setInterval(() => setId((id) => id + 1), delay); + return () => clearInterval(intervalId); + }, [delay]); + + const [status, setStatus] = React.useState(); + React.useEffect(() => { + const controller = new AbortController(); + fetchStatus(url, { signal: controller.signal }).then((result) => + setStatus(result) + ); + return () => controller.abort(); + // Trigger a re-fetch every so often + }, [id]); + + return status; +} +``` + +But this has a few downsides: +1. it changes the name of the hooks, so for error handling and similar, it can add some additional cognitive costs for devs, +2. can we parse 3rd party code? When wrapping hooks used in your app, you can automatically wrap all the used ones, so it's _fairly easy_. But detecting all the defined hooks can be more complicated (specifically as someone could name a regular function `useHello` without it being a hook), +3. in this example, we can see that we created the dependency array `[url, delay]`. But with original example, it created `[]` (because the variables were fully static.) So this creates more memory load as we aren't tracking exactly how those hooks are used, but how they are defined. # Adoption strategy -TO FILL +I have no idea. # How we teach this -TO FILL +As the compiler is a bit magical, I don’t if we need to teach that in a specific way. And if we do, we can mention something like "automatically wrap custom hooks in `useIsolation()` # Unresolved questions -TO FILL +Do we even want to apply the RFC https://github.com/reactjs/rfcs/pull/257? +Is it something that the compiler can do? +Is it the best way of automatically applying `useIsolation`? +Is it worth it really? From 53824c6f93001358e5f32cec2ad6e72f083d4d73 Mon Sep 17 00:00:00 2001 From: Benjamin Koltes Date: Sat, 30 Nov 2024 22:03:08 +0100 Subject: [PATCH 04/10] Update 0000-automate-use-isolation.md --- text/0000-automate-use-isolation.md | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/text/0000-automate-use-isolation.md b/text/0000-automate-use-isolation.md index a30af3c0..aab9333c 100644 --- a/text/0000-automate-use-isolation.md +++ b/text/0000-automate-use-isolation.md @@ -74,16 +74,16 @@ function useLongPoll(url, delay) { This topic is mostly for performance reasons, see [comment in the original RFC](https://github.com/Ayc0/react-rfcs/blob/main/text/0000-use-isolation.md#wrapping-existing-hooks-for-perf-optimizations-only). -One of the main problem when creating custom hooks / calling custom from 3rd party libraries, is that they can depend on their own update cycles, and they can create a lot of renders that may not be used in the end to drive UI changes. `useIsolation` introduced in another RFC can fix that, but developers still have to manually apply it when needed. +One of the main problems when creating custom hooks / calling custom from 3rd party libraries, is that they can depend on their own update cycles, and they can create a lot of renders that may not be used in the end to drive UI changes. `useIsolation` introduced in another RFC can fix that, but developers still have to manually apply it when needed. With the introduction of the React compiler, the compiler automatically applies the equivalent of `useMemo`, it seems fitting to also extend it to `useIsolation` (also as the React team planned to potentially extend `useMemo` to work exactly like this `useIsolation`, it was previously mentioned on Twitter, but I have no link to add here as those tweets have been deleted since). # Detailed design -We can use the same rule used in the React compiler that automatically wraps variables in `useMemo`, to detect when custom hooks are getting called (check their names match `/use[A-Z].*/`), and automatically wraps them in `useIsolation`. We can also use the same rule to check which variables to add in the dependencies array, or fallback to `[]` if no external variable is used. +We can use the same rule used in the React compiler that automatically wraps variables in `useMemo`, to detect when custom hooks are getting called (check if their names match `/use[A-Z].*/`), and automatically wraps them in `useIsolation`. We can also use the same rule to check which variables to add in the dependencies array, or fallback to `[]` if no external variable is used. > [!note] -> As mentioned in https://github.com/reactjs/rfcs/pull/257, the dependency array is not required for `useIsolation` to work. But this will allow fully skipping the call the hook if nothing changed, skipping a few checks (one for each hook used in those, no need to perform `useState` resolution, or cache checks for `useMemo` / `useCallback`, etc.). +> As mentioned in https://github.com/reactjs/rfcs/pull/257, the dependency array is not required for `useIsolation` to work. But this will allow fully skipping the call to the hook if nothing changed, skipping a few checks (one for each hook used in those, no need to perform `useState` resolution, or cache checks for `useMemo` / `useCallback`, etc.). > So this would still be a win: 1 cache check to avoid a lot # Drawbacks @@ -91,7 +91,7 @@ We can use the same rule used in the React compiler that automatically wraps var If the written code properly follows the rule of hooks, no code should depend on render cycles. So automatically applying `useIsolation()` should be fine. For the code paths not strictly following them, we can follow the current behavior of the compiler: not doing anything. -Also, this would add 1 `useIsolation` call in all component, adding an extra cache check for each component, which can make the memory usage higher, and potentially slow down (at least on initial mounts, and/or on non-properly memoized architecture). +Also, this would add 1 `useIsolation` call in all components, adding an extra cache check for each component, which can make the memory usage higher, and potentially slow down (at least on initial mounts, and/or on non-properly memoized architecture). # Alternatives @@ -164,7 +164,7 @@ function _useLongPoll(url, delay) { But this has a few downsides: 1. it changes the name of the hooks, so for error handling and similar, it can add some additional cognitive costs for devs, 2. can we parse 3rd party code? When wrapping hooks used in your app, you can automatically wrap all the used ones, so it's _fairly easy_. But detecting all the defined hooks can be more complicated (specifically as someone could name a regular function `useHello` without it being a hook), -3. in this example, we can see that we created the dependency array `[url, delay]`. But with original example, it created `[]` (because the variables were fully static.) So this creates more memory load as we aren't tracking exactly how those hooks are used, but how they are defined. +3. in this example, we can see that we created the dependency array `[url, delay]`. But with the original example, it created `[]` (because the variables were fully static.) So this creates more memory load as we aren't tracking exactly how those hooks are used, but how they are defined. # Adoption strategy @@ -179,4 +179,4 @@ As the compiler is a bit magical, I don’t if we need to teach that in a specif Do we even want to apply the RFC https://github.com/reactjs/rfcs/pull/257? Is it something that the compiler can do? Is it the best way of automatically applying `useIsolation`? -Is it worth it really? +Is it really worth it? From d2a5427ff1d2d5992b1b4c95d97e50313cce1385 Mon Sep 17 00:00:00 2001 From: Benjamin Koltes Date: Sat, 30 Nov 2024 22:18:32 +0100 Subject: [PATCH 05/10] Update 0000-automate-use-isolation.md --- text/0000-automate-use-isolation.md | 85 +++++++++++++++++++++++++++-- 1 file changed, 81 insertions(+), 4 deletions(-) diff --git a/text/0000-automate-use-isolation.md b/text/0000-automate-use-isolation.md index aab9333c..76e055fb 100644 --- a/text/0000-automate-use-isolation.md +++ b/text/0000-automate-use-isolation.md @@ -95,6 +95,8 @@ Also, this would add 1 `useIsolation` call in all components, adding an extra ca # Alternatives +## Wrap at definition + Instead of wrapping the call sites like proposed, potentially we could wrap the hooks at their definitions, like so: ```jsx @@ -166,6 +168,80 @@ But this has a few downsides: 2. can we parse 3rd party code? When wrapping hooks used in your app, you can automatically wrap all the used ones, so it's _fairly easy_. But detecting all the defined hooks can be more complicated (specifically as someone could name a regular function `useHello` without it being a hook), 3. in this example, we can see that we created the dependency array `[url, delay]`. But with the original example, it created `[]` (because the variables were fully static.) So this creates more memory load as we aren't tracking exactly how those hooks are used, but how they are defined. +## Wrap as `useMemo` + +I lied a bit about the React compiler: it does **not** add `useMemo`. Instead the following code: + +```jsx +function MyApp() { + const [state] = React.useState({}) + + const copied = React.useMemo(() => JSON.stringify(state), [state]) + + return {copied} +} +``` + +will be transformed into: + +```jsx +function MyApp() { + const $ = _c(5); + let t0; + if ($[0] === Symbol.for("react.memo_cache_sentinel")) { + t0 = {}; + $[0] = t0; + } else { + t0 = $[0]; + } + const [state] = React.useState(t0); + let t1; + let t2; + if ($[1] !== state) { + t2 = JSON.stringify(state); + $[1] = state; + $[2] = t2; + } else { + t2 = $[2]; + } + t1 = t2; + const copied = t1; + let t3; + if ($[3] !== copied) { + t3 = {copied}; + $[3] = copied; + $[4] = t3; + } else { + t3 = $[4]; + } + return t3; +} +``` + +And this piece of code is the equivalent of `const copied = React.useMemo(() => JSON.stringify(state), [state])`: + +```jsx + let t1; + let t2; + if ($[1] !== state) { + t2 = JSON.stringify(state); + $[1] = state; + $[2] = t2; + } else { + t2 = $[2]; + } + t1 = t2; + const copied = t1; +``` + +Potentially, if the React team ships the fact that `useMemo` can be used to wrap hooks too, we could use the same syntax for this RFC. + +I don't think it's possible (which is why I didn't start with this proposal), because in https://github.com/reactjs/rfcs/pull/257, I'm mentioning: + +> 2. Create a new internal _call scope_ (like a component) + +And adding those `if`s in the code can't. You need to, at least, add flags to mention that you're entering in a new component / hook _scope_. So it would be possible but with more changes to the compiler (which is above what I understand so I won't go into details.) + # Adoption strategy I have no idea. @@ -176,7 +252,8 @@ As the compiler is a bit magical, I don’t if we need to teach that in a specif # Unresolved questions -Do we even want to apply the RFC https://github.com/reactjs/rfcs/pull/257? -Is it something that the compiler can do? -Is it the best way of automatically applying `useIsolation`? -Is it really worth it? +- Do we even want to apply the RFC https://github.com/reactjs/rfcs/pull/257? +- Is it something that the compiler can do? +- Is it the best way of automatically applying `useIsolation`? +- If the React team prefers the `useMemo` approach, does it fit how the compiler already handles `useMemo`? +- Is it really worth it? From db73e57685e6f310fcf47031058e3a96eab9e933 Mon Sep 17 00:00:00 2001 From: Benjamin Koltes Date: Sat, 30 Nov 2024 22:20:20 +0100 Subject: [PATCH 06/10] Update 0000-automate-use-isolation.md --- text/0000-automate-use-isolation.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/text/0000-automate-use-isolation.md b/text/0000-automate-use-isolation.md index 76e055fb..4f604b82 100644 --- a/text/0000-automate-use-isolation.md +++ b/text/0000-automate-use-isolation.md @@ -164,9 +164,9 @@ function _useLongPoll(url, delay) { ``` But this has a few downsides: -1. it changes the name of the hooks, so for error handling and similar, it can add some additional cognitive costs for devs, -2. can we parse 3rd party code? When wrapping hooks used in your app, you can automatically wrap all the used ones, so it's _fairly easy_. But detecting all the defined hooks can be more complicated (specifically as someone could name a regular function `useHello` without it being a hook), -3. in this example, we can see that we created the dependency array `[url, delay]`. But with the original example, it created `[]` (because the variables were fully static.) So this creates more memory load as we aren't tracking exactly how those hooks are used, but how they are defined. +1. It changes the name of the hooks, so for error handling and similar, it can add some additional cognitive costs for devs, +2. Can we parse 3rd party code? When wrapping hooks used in your app, you can automatically wrap all the used ones, so it's _fairly easy_. But detecting all the defined hooks can be more complicated (specifically as someone could name a regular function `useHello` without it being a hook), +3. In this example, we can see that we created the dependency array `[url, delay]`. But with the original example, it created `[]` (because the variables were fully static.) So this creates more memory load as we aren't tracking exactly how those hooks are used, but how they are defined. ## Wrap as `useMemo` From 5e67fb1b7e2efaccd1985ec9f3dbc74a2c36c99e Mon Sep 17 00:00:00 2001 From: Benjamin Koltes Date: Sat, 30 Nov 2024 22:21:30 +0100 Subject: [PATCH 07/10] Update 0000-automate-use-isolation.md --- text/0000-automate-use-isolation.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/text/0000-automate-use-isolation.md b/text/0000-automate-use-isolation.md index 4f604b82..c7762c3d 100644 --- a/text/0000-automate-use-isolation.md +++ b/text/0000-automate-use-isolation.md @@ -182,7 +182,7 @@ function MyApp() { } ``` -will be transformed into: +will be transformed into ([see playground](https://playground.react.dev/#N4Igzg9grgTgxgUxALhAMygOzgFwJYSYAEAsgJ4CCADlQBQCURwAOsUXIWDkQNpcCGOBAF0iAXiIAlBP1wA6KGAQBlHIIS1gAX3qtWRdp24cqeBABNxUmfMUISCALYRaDcQD4iAKWUB5AHJyXDB4mADmeGhktAJC9AA0vLEiupj6RDAIOLDEADxgVPyY7sAmZuZauQD0BUXurFqsIFpAA)): ```jsx function MyApp() { From b740073ae0a5156b342d8f26d884a642d93d7e4a Mon Sep 17 00:00:00 2001 From: Benjamin Koltes Date: Sat, 30 Nov 2024 22:22:46 +0100 Subject: [PATCH 08/10] Update 0000-automate-use-isolation.md --- text/0000-automate-use-isolation.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/text/0000-automate-use-isolation.md b/text/0000-automate-use-isolation.md index c7762c3d..bab12bb0 100644 --- a/text/0000-automate-use-isolation.md +++ b/text/0000-automate-use-isolation.md @@ -240,7 +240,7 @@ I don't think it's possible (which is why I didn't start with this proposal), be > 2. Create a new internal _call scope_ (like a component) -And adding those `if`s in the code can't. You need to, at least, add flags to mention that you're entering in a new component / hook _scope_. So it would be possible but with more changes to the compiler (which is above what I understand so I won't go into details.) +And you can't do this by only adding those `if`s. Instead you at least need to add _flags_ indicating you're entering in a new component / hook _scope_. So it would be possible but with more changes to the compiler (which is above what I understand so I won't go into details.) # Adoption strategy From 46f6282c2221407101482f45396a8c1283e37e72 Mon Sep 17 00:00:00 2001 From: Benjamin Koltes Date: Sat, 30 Nov 2024 22:23:30 +0100 Subject: [PATCH 09/10] Update 0000-automate-use-isolation.md --- text/0000-automate-use-isolation.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/text/0000-automate-use-isolation.md b/text/0000-automate-use-isolation.md index bab12bb0..b60a9a0c 100644 --- a/text/0000-automate-use-isolation.md +++ b/text/0000-automate-use-isolation.md @@ -240,7 +240,7 @@ I don't think it's possible (which is why I didn't start with this proposal), be > 2. Create a new internal _call scope_ (like a component) -And you can't do this by only adding those `if`s. Instead you at least need to add _flags_ indicating you're entering in a new component / hook _scope_. So it would be possible but with more changes to the compiler (which is above what I understand so I won't go into details.) +And you can't do this by only adding those `if`s. Instead you at least need to add _flags_ indicating you're entering in a new component / hook _scope_. So more changes would have to be done to the compiler to make those work (which is above what I understand so I won't go into details.) # Adoption strategy From 5ae3a01ced54650f3b73e8ee73241e2ba3fa7092 Mon Sep 17 00:00:00 2001 From: Benjamin Koltes Date: Sat, 30 Nov 2024 22:36:16 +0100 Subject: [PATCH 10/10] Update 0000-automate-use-isolation.md --- text/0000-automate-use-isolation.md | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/text/0000-automate-use-isolation.md b/text/0000-automate-use-isolation.md index b60a9a0c..6388154f 100644 --- a/text/0000-automate-use-isolation.md +++ b/text/0000-automate-use-isolation.md @@ -234,13 +234,14 @@ And this piece of code is the equivalent of `const copied = React.useMemo(() => const copied = t1; ``` -Potentially, if the React team ships the fact that `useMemo` can be used to wrap hooks too, we could use the same syntax for this RFC. +Potentially, if the React team ships the fact that `useMemo` can be used to wrap hooks too, we could use the same syntax (with the tags `$[n]` and variables `tn`) for this RFC too. -I don't think it's possible (which is why I didn't start with this proposal), because in https://github.com/reactjs/rfcs/pull/257, I'm mentioning: +I don't think it's currently possible (with the current implementation of the compiler, I mean), because in https://github.com/reactjs/rfcs/pull/257, I'm mentioning: > 2. Create a new internal _call scope_ (like a component) -And you can't do this by only adding those `if`s. Instead you at least need to add _flags_ indicating you're entering in a new component / hook _scope_. So more changes would have to be done to the compiler to make those work (which is above what I understand so I won't go into details.) +And to the best of my knowledge, using those `if`s can't let you create those _call scope_. Maybe the compiler can be updated to allow defining them (I have no idea how, I don't have the knowledge about how React would define them / expose them.) +But if we just look at the current compiler output, I believe that addings those `$[n]` would be harder that keeping in the compiled code calls to `useMemo` **for hooks** optimizations. # Adoption strategy