Skip to content

Commit d9364e2

Browse files
committed
feat: add error 321 page, update skill rules, and add error reviewer
1 parent 023a392 commit d9364e2

File tree

3 files changed

+173
-23
lines changed

3 files changed

+173
-23
lines changed

.claude/skills/docs-writer-error/SKILL.md

Lines changed: 45 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -61,19 +61,31 @@ Place the file at `src/content/errors/{code}.md`. Use the template below.
6161
```mdx
6262
<Intro>
6363

64-
In the minified production build of React, we avoid sending down full error messages in order to reduce the number of bytes sent over the wire.
64+
This page explains this React error and common ways to fix it.
6565

6666
</Intro>
6767

68-
We highly recommend using the development build locally when debugging your app since it tracks additional debug info and provides helpful warnings about potential problems in your apps, but if you encounter an exception while using the production build, this page will reassemble the original error message.
69-
70-
The full text of the error you just encountered is:
68+
The full text of the error is:
7169

7270
<ErrorDecoder />
7371

72+
<Note>
73+
74+
In the minified production build of React, full error messages are replaced with short codes to reduce bundle size. We recommend using the development build when debugging, as it includes additional warnings and debug information.
75+
76+
</Note>
77+
7478
## What This Error Means {/*what-this-error-means*/}
7579

76-
[Plain-language explanation. 1-3 paragraphs.]
80+
[One-line opener ending with `:` — identifies the error condition]:
81+
82+
` ` `js {N}
83+
[Minimal code showing the broken pattern, with // 🔴 marker and line highlight]
84+
` ` `
85+
86+
[1-2 paragraphs explaining why this causes an error — what React was doing, what concept is involved.]
87+
88+
[See the examples below for common causes and how to fix them.](#common-causes)
7789

7890
## Common Causes {/*common-causes*/}
7991

@@ -103,6 +115,8 @@ Here is an example of code that would trigger this error:
103115

104116
</Sandpack>
105117

118+
[Optional: 1-2 sentences of supplementary context, e.g., related patterns or edge cases.]
119+
106120
## Related Documentation {/*related-documentation*/}
107121

108122
- [Link text](/path/to/page)
@@ -112,32 +126,39 @@ Here is an example of code that would trigger this error:
112126

113127
### Boilerplate (Required, Verbatim)
114128

115-
The `<Intro>` block, the paragraph about development builds, and `<ErrorDecoder />` must appear on every error page exactly as shown. Do not modify, reword, or omit any part.
129+
The `<Intro>` block, `<ErrorDecoder />`, and the `<Note>` about minified builds must appear on every custom error page exactly as shown in the template. Do not modify, reword, or omit any part. The intro leads with purpose ("explains this React error and common ways to fix it"), and the minification context is placed in a `<Note>` after the error decoder. The generic error page (`generic.md`) uses a different boilerplate — this skill only covers custom error pages.
116130

117131
### What This Error Means
118132

119-
- Open with: "This error occurs when [condition]."
120-
- Explain what React was doing when it threw the error.
121-
- If the message has `%s` placeholders, explain what each represents.
122-
- Do not repeat the error message text — `<ErrorDecoder />` already shows it.
123-
- Name the specific React concept involved.
124-
- Address the developer pain points found in research — if people commonly misunderstand why this error happens, address that confusion directly.
133+
**Structure (in order):**
134+
1. Open with "This error occurs when [condition]:" — one sentence, ending with a colon, linking to relevant docs if applicable.
135+
2. Show a plain fenced code block (not Sandpack) with the broken pattern — use `{N}` line highlighting on the problematic line and a `// 🔴` comment marker.
136+
3. Explain why this causes an error in 1-2 paragraphs — what React was doing, what concept is involved. Address the developer pain points found in research — if people commonly misunderstand why this error happens, address that confusion directly.
137+
4. End with: `[See the examples below for common causes and how to fix them.](#common-causes)`
138+
139+
**Rules:**
140+
- The code block is a quick illustrative snippet, NOT an interactive Sandpack — it gives the reader instant visual recognition of the broken pattern.
141+
- Use line highlighting (`{N}`) to point to the exact problematic line.
142+
- The `// 🔴` marker comment in the code block may reference the error concept (e.g., `// 🔴 Invalid Hook call!`).
143+
- If the message has `%s` placeholders, explain what each represents in the explanation paragraphs.
144+
- The explanation paragraphs follow the code — "show, then explain."
145+
- Keep the code block minimal (under ~15 lines) — just enough to show the pattern.
125146

126-
**Opening sentence patterns:**
147+
**Opening sentence patterns** (all end with `:`):
127148

128149
| Category | Pattern |
129150
|----------|---------|
130-
| Hooks | "This error occurs when a Hook is called in a way that violates the [Rules of Hooks](/reference/rules/rules-of-hooks)." |
131-
| Rendering | "This error occurs when React encounters [invalid element/children] during rendering." |
132-
| Hydration | "This error occurs when the HTML generated by the server does not match what the client renders." |
133-
| Server Components | "This error occurs when a value that is not serializable is passed from a Server Component to a Client Component." |
134-
| Suspense | "This error occurs when a component suspends during rendering without a `<Suspense>` boundary to catch it." |
151+
| Hooks | "This error occurs when a Hook is called in a way that violates the [Rules of Hooks](/reference/rules/rules-of-hooks):" |
152+
| Rendering | "This error occurs when React encounters [invalid element/children] during rendering:" |
153+
| Hydration | "This error occurs when the HTML generated by the server does not match what the client renders:" |
154+
| Server Components | "This error occurs when a value that is not serializable is passed from a Server Component to a Client Component:" |
155+
| Suspense | "This error occurs when a component suspends during rendering without a `<Suspense>` boundary to catch it:" |
135156

136157
### Common Causes
137158

138159
- 1-4 causes per page. Most errors have 2-3.
139160
- Each cause gets its own `###` heading under `## Common Causes`.
140-
- Each cause must include: prose explanation, Problem Sandpack, Solution Sandpack.
161+
- Each cause must include: prose explanation, and either a Problem/Solution Sandpack pair, or plain code blocks. Build/configuration causes may use diagnostic commands and fix snippets instead.
141162
- Use descriptive headings: "Calling a Hook inside a condition", not "Cause 1".
142163
- **Order by real-world frequency**: Use web search and GitHub issue data from the research to determine which causes developers hit most often. The most common cause goes first.
143164
- **Address real confusion**: If the research shows developers struggle to understand why a particular pattern causes this error, explain it clearly in the prose.
@@ -156,6 +177,7 @@ For general Sandpack conventions, invoke `/docs-sandpack`.
156177

157178
- Mark problematic code with `// 🔴`.
158179
- Keep examples minimal — only code needed to trigger the error.
180+
- When the error being documented also triggers a lint rule, include `// eslint-disable-next-line` to suppress the lint error so the Sandpack demonstrates the runtime behavior.
159181
- Must have `export default` in main file.
160182
- **Base examples on real-world patterns** found in web search results — not abstract/contrived scenarios.
161183

@@ -255,7 +277,7 @@ Keep these pages minimal. Do not invent common causes.
255277

256278
**Do:**
257279
- Invoke `/react-expert error <CODE>` before writing
258-
- Use the boilerplate verbatim
280+
- Use the boilerplate verbatim (intro, error decoder, minification note)
259281
- Explain what `%s` placeholders represent
260282
- Show problem code before solution (problem-first)
261283
- Keep Sandpack examples minimal
@@ -268,7 +290,7 @@ Keep these pages minimal. Do not invent common causes.
268290
**Don't:**
269291
- Write error pages without research
270292
- Add frontmatter to error pages
271-
- Modify the boilerplate text
293+
- Modify the boilerplate text (intro, error decoder, or minification note)
272294
- Repeat the error message in prose
273295
- Include more than 4 causes
274296
- Use contrived/abstract examples when real-world patterns exist
@@ -280,11 +302,11 @@ Keep these pages minimal. Do not invent common causes.
280302
## Critical Rules
281303

282304
1. **Research first:** Always invoke `/react-expert error <CODE>` before writing.
283-
2. **Boilerplate is sacred:** `<Intro>`, dev build paragraph, and `<ErrorDecoder />` must appear verbatim.
305+
2. **Boilerplate is sacred:** `<Intro>`, `<ErrorDecoder />`, and the minification `<Note>` must appear verbatim on every custom error page.
284306
3. **No frontmatter:** Error pages have no YAML frontmatter.
285307
4. **All headings require IDs:** `## Title {/*title-id*/}` in kebab-case.
286308
5. **Problem-first Sandpacks:** Show broken code before the fix.
287-
6. **One pair per cause:** Each cause gets one problem + one solution Sandpack (or plain code blocks).
309+
6. **One pair per cause:** Each cause gets one problem + one solution Sandpack (or plain code blocks). Exception: build/configuration causes (e.g., duplicate packages) may use diagnostic commands and fix snippets instead of a strict problem/solution pair.
288310
7. **Real-world examples:** Base Sandpack examples on patterns from web research, not contrived scenarios.
289311
8. **No consecutive callouts:** Separate `<Pitfall>`/`<Note>` with prose.
290312
9. **Minimal examples:** Keep Sandpack files under 50 lines when possible.

.claude/skills/review-docs/SKILL.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ Run these tasks in parallel for the given file(s). Each agent checks different a
99
- [ ] Ask docs-reviewer agent to review {files} with docs-writer-learn (only for files in src/content/learn/).
1010
- [ ] Ask docs-reviewer agent to review {files} with docs-writer-reference (only for files in src/content/reference/).
1111
- [ ] Ask docs-reviewer agent to review {files} with docs-writer-blog (only for files in src/content/blog/).
12+
- [ ] Ask docs-reviewer agent to review {files} with docs-writer-error (only for files in src/content/errors/).
1213
- [ ] Ask docs-reviewer agent to review {files} with docs-voice (all documentation files).
1314
- [ ] Ask docs-reviewer agent to review {files} with docs-components (all documentation files).
1415
- [ ] Ask docs-reviewer agent to review {files} with docs-sandpack (files containing Sandpack examples).

src/content/errors/321.md

Lines changed: 127 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,127 @@
1+
<Intro>
2+
3+
This page explains this React error and common ways to fix it.
4+
5+
</Intro>
6+
7+
The full text of the error is:
8+
9+
<ErrorDecoder />
10+
11+
<Note>
12+
13+
In the minified production build of React, full error messages are replaced with short codes to reduce bundle size. We recommend using the development build when debugging, as it includes additional warnings and debug information.
14+
15+
</Note>
16+
17+
## What This Error Means {/*what-this-error-means*/}
18+
19+
This error occurs when a Hook is called in a way that violates the [Rules of Hooks](/reference/rules/rules-of-hooks):
20+
21+
```js {4}
22+
export default function Counter() {
23+
function handleClick() {
24+
// 🔴 Invalid Hook call!
25+
const [count, setCount] = useState(0);
26+
setCount(count + 1);
27+
}
28+
29+
return <button onClick={handleClick}>Click me</button>;
30+
}
31+
```
32+
33+
You can only call Hooks at the top level of a function component or a custom Hook. React tracks Hooks by associating them with the component that is currently rendering. When you call a Hook and no component is rendering, React cannot associate the Hook with a component, and throws this error.
34+
35+
The most common cause is calling a Hook outside a function component. For example, inside an event handler, a class component, or a regular function. Another common cause is having **multiple copies of React** loaded in your app, which is a build configuration problem, not a coding mistake.
36+
37+
[See the examples below for common causes and how to fix them.](#common-causes)
38+
39+
## Common Causes {/*common-causes*/}
40+
41+
### Calling a Hook outside the body of a function component {/*calling-a-hook-outside-the-body-of-a-function-component*/}
42+
43+
React requires you to call Hooks at the top level of a function component or a custom Hook—not inside event handlers, nested functions, or class components.
44+
45+
Here is an example of code that would trigger this error:
46+
47+
<Sandpack>
48+
49+
```js {expectedErrors: {'react-compiler': [7]}}
50+
import { useState } from 'react';
51+
52+
export default function Counter() {
53+
function handleClick() {
54+
// 🔴 useState is called inside an event handler, not the component body
55+
// eslint-disable-next-line react-hooks/rules-of-hooks
56+
const [count, setCount] = useState(0);
57+
setCount(count + 1);
58+
}
59+
60+
return <button onClick={handleClick}>Click me</button>;
61+
}
62+
```
63+
64+
</Sandpack>
65+
66+
To fix this, move the Hook call to the top level of your component:
67+
68+
<Sandpack>
69+
70+
```js
71+
import { useState } from 'react';
72+
73+
// ✅ Fixed: useState is called at the top level of the component
74+
export default function Counter() {
75+
const [count, setCount] = useState(0);
76+
77+
function handleClick() {
78+
setCount(count + 1);
79+
}
80+
81+
return <button onClick={handleClick}>Count: {count}</button>;
82+
}
83+
```
84+
85+
</Sandpack>
86+
87+
The same rule applies to class components—you cannot use Hooks in class components. If you need state or other React features in a class component, [convert it to a function component](/reference/react/Component#alternatives).
88+
89+
### Multiple copies of React in your app {/*multiple-copies-of-react*/}
90+
91+
If your project uses a monorepo, `npm link`, or a third-party package that bundles its own copy of React, you can end up with two separate copies of React loaded at the same time. When this happens, the copy of React that your component uses is different from the copy that `react-dom` uses, and Hooks break because React can't track them across copies.
92+
93+
To check if this is your problem, run the following from your project root:
94+
95+
```bash
96+
npm ls react
97+
```
98+
99+
If you see more than one entry for `react`, you have duplicate copies. You can also add a temporary log to confirm. Add this at the top of your component file:
100+
101+
```js
102+
import React from 'react';
103+
console.log(React === window.React); // false means duplicates
104+
```
105+
106+
If you're using webpack, you can fix this by adding a resolve alias in your webpack config:
107+
108+
```js
109+
// webpack.config.js
110+
module.exports = {
111+
resolve: {
112+
alias: {
113+
react: require.resolve('react'),
114+
'react-dom': require.resolve('react-dom'),
115+
},
116+
},
117+
};
118+
```
119+
120+
If you're using Vite, add a similar alias in your Vite config. For other bundlers, consult their documentation on how to configure module aliases.
121+
122+
## Related Documentation {/*related-documentation*/}
123+
124+
- [Rules of Hooks](/reference/rules/rules-of-hooks)
125+
- [`useState`](/reference/react/useState)
126+
- [Your First Component](/learn/your-first-component)
127+
- [Reusing Logic with Custom Hooks](/learn/reusing-logic-with-custom-hooks)

0 commit comments

Comments
 (0)