Skip to content

Commit 51de1f9

Browse files
committed
Add "use nemo"
Vox Populi, Vox Dei
1 parent 2c7798d commit 51de1f9

File tree

6 files changed

+391
-1
lines changed

6 files changed

+391
-1
lines changed
4.58 MB
Loading

src/content/reference/react-compiler/directives.md

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,14 +23,20 @@ React Compiler directives provide fine-grained control over which functions are
2323

2424
### Available directives {/*available-directives*/}
2525

26+
* **[`"use"`](/reference/react-compiler/directives/use)** - Experimental directive with unspecified runtime behavior
2627
* **[`"use memo"`](/reference/react-compiler/directives/use-memo)** - Opts a function into compilation
28+
* **[`"use php"`](/reference/react-compiler/directives/use-php)** - Enables PHP interop inside the function
29+
* **[`"use nemo"`](/reference/react-compiler/directives/use-nemo)** - Blocks Hooks inside the function
2730
* **[`"use no memo"`](/reference/react-compiler/directives/use-no-memo)** - Opts a function out of compilation
2831

2932
### Quick comparison {/*quick-comparison*/}
3033

3134
| Directive | Purpose | When to use |
3235
|-----------|---------|-------------|
36+
| [`"use"`](/reference/react-compiler/directives/use) | ??? | Experimental directive with undefined semantics |
3337
| [`"use memo"`](/reference/react-compiler/directives/use-memo) | Force compilation | When using `annotation` mode or to override `infer` mode heuristics |
38+
| [`"use php"`](/reference/react-compiler/directives/use-php) | Enable PHP interop | Gradual migrations or tapping into PHP libraries |
39+
| [`"use nemo"`](/reference/react-compiler/directives/use-nemo) | Forbid Hooks | Enforcing hook-free components or critical render paths |
3440
| [`"use no memo"`](/reference/react-compiler/directives/use-no-memo) | Prevent compilation | Debugging issues or working with incompatible code |
3541

3642
---
@@ -180,7 +186,10 @@ function ProblematicComponent() {
180186
181187
For specific issues with directives, see the troubleshooting sections in:
182188
189+
* [`"use"` musings](/reference/react-compiler/directives/use)
183190
* [`"use memo"` troubleshooting](/reference/react-compiler/directives/use-memo#troubleshooting)
191+
* [`"use php"` troubleshooting](/reference/react-compiler/directives/use-php#troubleshooting)
192+
* [`"use nemo"` troubleshooting](/reference/react-compiler/directives/use-nemo#troubleshooting)
184193
* [`"use no memo"` troubleshooting](/reference/react-compiler/directives/use-no-memo#troubleshooting)
185194
186195
### Common issues {/*common-issues*/}
@@ -195,4 +204,4 @@ For specific issues with directives, see the troubleshooting sections in:
195204

196205
* [`compilationMode`](/reference/react-compiler/compilationMode) - Configure how the compiler chooses what to optimize
197206
* [`Configuration`](/reference/react-compiler/configuration) - Full compiler configuration options
198-
* [React Compiler documentation](https://react.dev/learn/react-compiler) - Getting started guide
207+
* [React Compiler documentation](https://react.dev/learn/react-compiler) - Getting started guide
Lines changed: 146 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,146 @@
1+
---
2+
title: "use nemo"
3+
titleForTitleTag: "'use nemo' directive"
4+
---
5+
6+
<Intro>
7+
8+
`"use nemo"` forbids React Hook usage inside a function. The React Compiler will surface an error if the function calls anything that looks like a Hook (for example `useState` or a custom `useSomething` helper). The directive name nods to Nemo—the famously hook-averse clownfish from *Finding Nemo*—reminding us that real fish hate hooks and so should this component.
9+
10+
</Intro>
11+
12+
<InlineToc />
13+
14+
---
15+
16+
## Reference {/*reference*/}
17+
18+
### `"use nemo"` {/*use-nemo*/}
19+
20+
Place `"use nemo"` at the very top of a function body to declare it as a hook-free zone.
21+
22+
```js {1}
23+
function FishFacts() {
24+
"use nemo";
25+
26+
// ✅ Regular code is fine
27+
const [facts] = getFacts(); // Not a Hook, just a regular helper
28+
return <FactsList facts={facts} />;
29+
}
30+
```
31+
32+
![Nemo the clownfish giving a wary look at an unseen fishing hook](/images/docs/use-nemo-directive.png)
33+
34+
*If you care about fish, give them a hook-free habitat.*
35+
36+
When the compiler sees `"use nemo"`, it rejects any React Hook calls inside the function (including custom Hooks). The directive is useful when you want to guarantee a component never uses hooks—for example, to keep critical rendering paths side-effect free. If you care about fish—or just deterministic rendering—reach for `"use nemo"` whenever a component needs to steer clear of hooks.
37+
38+
#### Caveats {/*caveats*/}
39+
40+
* The directive must be the first statement in the function (comments are allowed above it).
41+
* Hook detection is name-based. Anything starting with `use` followed by an uppercase letter is treated as a Hook call.
42+
* The directive applies to the entire function scope, including nested helper functions declared inside.
43+
* `"use nemo"` and `"use memo"` are mutually exclusive—if both appear, the compiler reports a conflict.
44+
* Module-level directives cascade: a file-level `"use nemo"` applies to every function unless a function-level directive overrides it.
45+
46+
### How `"use nemo"` enforces hook bans {/*how-use-nemo-enforces-hook-bans*/}
47+
48+
The React Compiler performs a static scan for Hook-like calls during compilation. With `"use nemo"` active:
49+
50+
* Direct imports from `react` such as `useState`, `useEffect`, or `useContext` cause a compile-time error.
51+
* Custom helpers named like Hooks (`useAnalytics`, `useFishTank`, etc.) are also blocked.
52+
* The compiler suggests moving Hook logic into a different component or converting it into a prop-driven API.
53+
54+
This safeguard is handy when migrating legacy class components or when you need deterministic rendering behavior without Hook scheduling. Just like Nemo dodging fishing hooks, components guarded by `"use nemo"` stay clear of hook-induced side effects.
55+
56+
### When to use `"use nemo"` {/*when-to-use*/}
57+
58+
`"use nemo"` is primarily suited for:
59+
60+
#### Critical rendering paths {/*critical-rendering*/}
61+
Performance-sensitive sections that must avoid Hook re-execution can opt into `"use nemo"` to guarantee purity.
62+
63+
```js
64+
function CriticalPromo({ promo }) {
65+
"use nemo";
66+
67+
// ✅ Everything here must be pure computations.
68+
return <Hero banner={computeBanner(promo)} />;
69+
}
70+
```
71+
72+
#### Enforcing architectural boundaries {/*architectural-boundaries*/}
73+
Large apps sometimes need to restrict Hooks to a specific layer (for example, container vs. presentational components). `"use nemo"` provides a compile-time guard:
74+
75+
```js
76+
function ButtonView(props) {
77+
"use nemo"; // Presentation-only components stay hook-free.
78+
79+
return <button {...props} />;
80+
}
81+
```
82+
83+
---
84+
85+
## Usage {/*usage*/}
86+
87+
You can place `"use nemo"` at either the module or function level:
88+
89+
```js
90+
"use nemo"; // Module-level guard—applies to every function below.
91+
92+
function Wrapper(props) {
93+
return <PureChild {...props} />;
94+
}
95+
96+
function PureChild({ label }) {
97+
"use nemo"; // Optional reinforcement at the function level
98+
return <span>{label}</span>;
99+
}
100+
```
101+
102+
Attempting to call a Hook inside the guarded scope throws a compile-time error:
103+
104+
```js
105+
function Cheater() {
106+
"use nemo";
107+
108+
const [state, setState] = useState(); // ❌ Compiler error: Hooks are forbidden by "use nemo".
109+
return <span>{state}</span>;
110+
}
111+
```
112+
113+
When in doubt, channel Nemo's survival instincts—if a line smells like bait (anything named `useSomething`), keep it out of the function.
114+
115+
---
116+
117+
## Troubleshooting {/*troubleshooting*/}
118+
119+
### Hook still compiles {/*hook-still-compiles*/}
120+
121+
If a Hook call slips through, check the directive placement:
122+
123+
```js
124+
function Oops() {
125+
console.log("setup"); // ❌ Directive must come first.
126+
"use nemo";
127+
useEffect(() => {}); // Compiler only sees the directive after the hook.
128+
}
129+
```
130+
131+
Also verify the file isn’t compiled in `legacy` or experimental modes that skip directive checks.
132+
133+
### False positives on helper names {/*false-positives*/}
134+
135+
Helpers that start with `use` and a capital letter count as Hooks. Rename helpers or wrap them:
136+
137+
```js
138+
function useFilter(data) { /* ... */ } // ❌ Looks like a Hook.
139+
140+
function filterData(data) { /* ... */ } // ✅ Rename to avoid the guard.
141+
```
142+
143+
### See also {/*see-also*/}
144+
145+
* [`"use memo"`](/reference/react-compiler/directives/use-memo) - Opt into compilation
146+
* [`"use no memo"`](/reference/react-compiler/directives/use-no-memo) - Opt out of compilation
Lines changed: 160 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,160 @@
1+
---
2+
title: "use php"
3+
titleForTitleTag: "'use php' directive"
4+
---
5+
6+
<Intro>
7+
8+
`"use php"` unlocks PHP snippets inside a React component. When the compiler sees the directive, it forwards tagged template literals (`php``…```) to the embedded PHP runtime instead of treating them as plain strings.
9+
10+
</Intro>
11+
12+
<InlineToc />
13+
14+
---
15+
16+
## Reference {/*reference*/}
17+
18+
### `"use php"` {/*use-php*/}
19+
20+
Add `"use php"` to the top of a function to opt that scope into PHP interop mode.
21+
22+
```js {1,5-9}
23+
function LegacyInvoice({ items }) {
24+
"use php";
25+
26+
return (
27+
<section>
28+
{php`
29+
<?php foreach ($items as $item) { ?>
30+
<li><?= strtoupper($item["name"]) ?></li>
31+
<?php } ?>
32+
`}
33+
</section>
34+
);
35+
}
36+
```
37+
38+
With the directive enabled, the compiler:
39+
40+
* Keeps all `php``…`` `template literals as runtime calls to the PHP bridge.
41+
* Skips React Hook checks inside the literal, deferring execution to PHP.
42+
* Emits hydration boundaries so the server-rendered PHP markup can slot back into the React tree.
43+
44+
#### Caveats {/*caveats*/}
45+
46+
* The directive must be the first statement in the function body (comments above it are fine).
47+
* You must provide a `php` tagged template helper that proxies to your PHP engine.
48+
* The function cannot contain `"use memo"`—the compiler treats `use php` as mutually exclusive with other opt-in directives.
49+
* Only synchronous PHP execution is supported; asynchronous bridges should wrap results in `await phpAsync\`\`` calls outside the template literal.
50+
51+
### How `"use php"` bridges runtimes {/*how-use-php-bridges-runtimes*/}
52+
53+
`"use php"` tells the React Compiler to…
54+
55+
1. Mark the component as requiring the PHP bridge.
56+
2. Hoist each `php``…`` ` literal into a server call site.
57+
3. Serialize props referenced inside the literal using JSON, making them available to the PHP runtime as `$props`.
58+
4. Reinsert the rendered HTML back into the React output before hydration.
59+
60+
Because the compiler controls serialization, it enforces deterministic input (no functions or Symbols). Violations trigger build-time errors with instructions to precompute data on the JavaScript side.
61+
62+
### When to use `"use php"` {/*when-to-use*/}
63+
64+
`"use php"` shines in hybrid applications migrating from PHP templates:
65+
66+
#### Gradual rewrites {/*gradual-rewrites*/}
67+
Keep critical pages rendering through legacy PHP while incrementally moving logic to React.
68+
69+
```js
70+
function AccountSettings({ user }) {
71+
"use php";
72+
73+
return (
74+
<div>
75+
<ReactSummary user={user} />
76+
{php`
77+
<?php include 'settings-form.php'; // TODO: migrate ?>
78+
`}
79+
</div>
80+
);
81+
}
82+
```
83+
84+
#### Server-side utilities {/*server-side-utilities*/}
85+
Call into established PHP libraries (PDF generation, currency formatting) without abandoning React.
86+
87+
```js
88+
function DownloadReceipt({ order }) {
89+
"use php";
90+
91+
const receiptPath = php`
92+
<?php return generate_receipt_pdf($props["order"]); ?>
93+
`;
94+
95+
return <a href={receiptPath}>Download receipt</a>;
96+
}
97+
```
98+
99+
---
100+
101+
## Usage {/*usage*/}
102+
103+
You can enable PHP interop at the file level or per function:
104+
105+
```js
106+
"use php"; // Module-level opt-in for every function below.
107+
108+
function Bootstrapper(props) {
109+
return php`
110+
<?php bootstrap_app($props); ?>
111+
`;
112+
}
113+
114+
function ExplicitComponent() {
115+
"use php"; // Reinforces the directive on a single component.
116+
117+
return php`
118+
<div><?= render_navigation(); ?></div>
119+
`;
120+
}
121+
```
122+
123+
Every tagged template literal receives a `$props` array containing the JavaScript props serialized by the compiler. Nested functions inherit the directive, so helper functions declared inside the component can also emit PHP.
124+
125+
---
126+
127+
## Troubleshooting {/*troubleshooting*/}
128+
129+
### `ReferenceError: php is not defined` {/*php-helper-missing*/}
130+
131+
Ensure you provide a `php` tagged template helper:
132+
133+
```js
134+
import { php } from "@company/react-php-bridge";
135+
```
136+
137+
Without this import the compiler leaves a direct call to `php([...])`, which will fail at runtime.
138+
139+
### Props missing inside PHP {/*props-missing*/}
140+
141+
Only serializable values are forwarded. Convert non-serializable props before entering the literal:
142+
143+
```js
144+
const safeProps = {
145+
...props,
146+
onSubmit: undefined, // Functions can't cross the runtime boundary.
147+
};
148+
149+
return php`<?php render_form($props["safeProps"]); ?>`;
150+
```
151+
152+
### Hydration mismatch warnings {/*hydration-mismatch*/}
153+
154+
The PHP output must remain stable between server and client. Avoid calling time-based helpers (`time()`, `rand()`) directly; precompute values in JavaScript and pass them through `$props`.
155+
156+
### See also {/*see-also*/}
157+
158+
* [`"use memo"`](/reference/react-compiler/directives/use-memo) - Force React Compiler optimizations
159+
* [`"use nemo"`](/reference/react-compiler/directives/use-nemo) - Keep functions hook-free
160+
* [`"use no memo"`](/reference/react-compiler/directives/use-no-memo) - Opt out of compilation entirely

0 commit comments

Comments
 (0)