diff --git a/.babelrc b/.babelrc deleted file mode 100644 index 40f742563..000000000 --- a/.babelrc +++ /dev/null @@ -1,41 +0,0 @@ -{ - "presets": [ - [ - "@babel/preset-env", - { - "loose": true, - "modules": false, - "useBuiltIns": "usage", - "shippedProposals": true, - "targets": { - "browsers": [">0.25%", "not dead"], - } - } - ], - [ - "@babel/preset-react", - { - "useBuiltIns": true, - "pragma": "React.createElement", - } - ], - "@babel/flow" - ], - "plugins": [ - [ - "@babel/plugin-proposal-class-properties", - { - "loose": true - } - ], - "@babel/plugin-syntax-dynamic-import", - "babel-plugin-macros", - [ - "@babel/plugin-transform-runtime", - { - "helpers": true, - "regenerator": true - } - ] - ] -} \ No newline at end of file diff --git a/.circleci/config.yml b/.circleci/config.yml deleted file mode 100644 index 9065da7b5..000000000 --- a/.circleci/config.yml +++ /dev/null @@ -1,23 +0,0 @@ -version: 2 -jobs: - build: - docker: - - image: circleci/node:12 - steps: - - checkout - - restore_cache: - keys: - - dependencies-{{ checksum "yarn.lock" }} - - run: - name: Install - command: yarn install --pure-lockfile - - save_cache: - paths: - - node_modules - key: dependencies-{{ checksum "yarn.lock" }} - - run: - name: Check Prettier, ESLint, Flow - command: yarn ci-check - - run: - name: Test Textlint - command: yarn test:textlint diff --git a/.claude/agents/docs-reviewer.md b/.claude/agents/docs-reviewer.md new file mode 100644 index 000000000..af0a856e4 --- /dev/null +++ b/.claude/agents/docs-reviewer.md @@ -0,0 +1,28 @@ +--- +name: docs-reviewer +description: "Lean docs reviewer that dispatches reviews docs for a particular skill." +model: opus +color: cyan +--- + +You are a direct, critical, expert reviewer for React documentation. + +Your role is to use given skills to validate given doc pages for consistency, correctness, and adherence to established patterns. + +Complete this process: + +## Phase 1: Task Creation +1. CRITICAL: Read the skill requested. +2. Understand the skill's requirements. +3. Create a task list to validate skills requirements. + +## Phase 2: Validate + +1. Read the docs files given. +2. Review each file with the task list to verify. + +## Phase 3: Respond + +You must respond with a checklist of the issues you identified, and line number. + +DO NOT respond with passed validations, ONLY respond with the problems. diff --git a/.claude/settings.json b/.claude/settings.json new file mode 100644 index 000000000..111403183 --- /dev/null +++ b/.claude/settings.json @@ -0,0 +1,32 @@ +{ + "skills": { + "suggest": [ + { + "pattern": "src/content/learn/**/*.md", + "skill": "docs-writer-learn" + }, + { + "pattern": "src/content/reference/**/*.md", + "skill": "docs-writer-reference" + } + ] + }, + "permissions": { + "allow": [ + "Skill(docs-voice)", + "Skill(docs-components)", + "Skill(docs-sandpack)", + "Skill(docs-rsc-sandpack)", + "Skill(docs-writer-learn)", + "Skill(docs-writer-reference)", + "Bash(yarn lint:*)", + "Bash(yarn lint-heading-ids:*)", + "Bash(yarn lint:fix:*)", + "Bash(yarn tsc:*)", + "Bash(yarn check-all:*)", + "Bash(yarn fix-headings:*)", + "Bash(yarn deadlinks:*)", + "Bash(yarn prettier:diff:*)" + ] + } +} diff --git a/.claude/skills/docs-components/SKILL.md b/.claude/skills/docs-components/SKILL.md new file mode 100644 index 000000000..4b75f27a1 --- /dev/null +++ b/.claude/skills/docs-components/SKILL.md @@ -0,0 +1,518 @@ +--- +name: docs-components +description: Comprehensive MDX component patterns (Note, Pitfall, DeepDive, Recipes, etc.) for all documentation types. Authoritative source for component usage, examples, and heading conventions. +--- + +# MDX Component Patterns + +## Quick Reference + +### Component Decision Tree + +| Need | Component | +|------|-----------| +| Helpful tip or terminology | `` | +| Common mistake warning | `` | +| Advanced technical explanation | `` | +| Canary-only feature | `` or `` | +| Server Components only | `` | +| Deprecated API | `` | +| Experimental/WIP | `` | +| Visual diagram | `` | +| Multiple related examples | `` | +| Interactive code | `` (see `/docs-sandpack`) | +| Console error display | `` | +| End-of-page exercises | `` (Learn pages only) | + +### Heading Level Conventions + +| Component | Heading Level | +|-----------|---------------| +| DeepDive title | `####` (h4) | +| Titled Pitfall | `#####` (h5) | +| Titled Note | `####` (h4) | +| Recipe items | `####` (h4) | +| Challenge items | `####` (h4) | + +### Callout Spacing Rules + +Callout components (Note, Pitfall, DeepDive) require a **blank line after the opening tag** before content begins. + +**Never place consecutively:** +- `` followed by `` - Combine into one with titled subsections, or separate with prose +- `` followed by `` - Combine into one, or separate with prose + +**Allowed consecutive patterns:** +- `` followed by `` - OK for multi-part explorations (see useMemo.md) +- `` followed by `` - OK when DeepDive explains "why" behind the Pitfall + +**Separation content:** Prose paragraphs, code examples (Sandpack), or section headers. + +**Why:** Consecutive warnings create a "wall of cautions" that overwhelms readers and causes important warnings to be skimmed. + +**Incorrect:** +```mdx + +Don't do X. + + + +Don't do Y. + +``` + +**Correct - combined:** +```mdx + + +##### Don't do X {/*pitfall-x*/} +Explanation. + +##### Don't do Y {/*pitfall-y*/} +Explanation. + + +``` + +**Correct - separated:** +```mdx + +Don't do X. + + +This leads to another common mistake: + + +Don't do Y. + +``` + +--- + +## `` + +Important clarifications, conventions, or tips. Less severe than Pitfall. + +### Simple Note + +```mdx + + +The optimization of caching return values is known as [_memoization_](https://en.wikipedia.org/wiki/Memoization). + + +``` + +### Note with Title + +Use `####` (h4) heading with an ID. + +```mdx + + +#### There is no directive for Server Components. {/*no-directive*/} + +A common misunderstanding is that Server Components are denoted by `"use server"`, but there is no directive for Server Components. The `"use server"` directive is for Server Functions. + + +``` + +### Version-Specific Note + +```mdx + + +Starting in React 19, you can render `` as a provider. + +In older versions of React, use ``. + + +``` + +--- + +## `` + +Common mistakes that cause bugs. Use for errors readers will likely make. + +### Simple Pitfall + +```mdx + + +We recommend defining components as functions instead of classes. [See how to migrate.](#alternatives) + + +``` + +### Titled Pitfall + +Use `#####` (h5) heading with an ID. + +```mdx + + +##### Calling different memoized functions will read from different caches. {/*pitfall-different-caches*/} + +To access the same cache, components must call the same memoized function. + + +``` + +### Pitfall with Wrong/Right Code + +```mdx + + +##### `useFormStatus` will not return status information for a `
` rendered in the same component. {/*pitfall-same-component*/} + +```js +function Form() { + // πŸ”΄ `pending` will never be true + const { pending } = useFormStatus(); + return
; +} +``` + +Instead call `useFormStatus` from inside a component located inside `
`. + + +``` + +--- + +## `` + +Optional deep technical content. **First child must be `####` heading with ID.** + +### Standard DeepDive + +```mdx + + +#### Is using an updater always preferred? {/*is-updater-preferred*/} + +You might hear a recommendation to always write code like `setAge(a => a + 1)` if the state you're setting is calculated from the previous state. There's no harm in it, but it's also not always necessary. + +In most cases, there is no difference between these two approaches. React always makes sure that for intentional user actions, like clicks, the `age` state variable would be updated before the next click. + + +``` + +### Comparison DeepDive + +For comparing related concepts: + +```mdx + + +#### When should I use `cache`, `memo`, or `useMemo`? {/*cache-memo-usememo*/} + +All mentioned APIs offer memoization but differ in what they memoize, who can access the cache, and when their cache is invalidated. + +#### `useMemo` {/*deep-dive-usememo*/} + +In general, you should use `useMemo` for caching expensive computations in Client Components across renders. + +#### `cache` {/*deep-dive-cache*/} + +In general, you should use `cache` in Server Components to memoize work that can be shared across components. + + +``` + +--- + +## `` + +Multiple related examples showing variations. Each recipe needs ``. + +```mdx + + +#### Counter (number) {/*counter-number*/} + +In this example, the `count` state variable holds a number. + + +{/* code */} + + + + +#### Text field (string) {/*text-field-string*/} + +In this example, the `text` state variable holds a string. + + +{/* code */} + + + + + +``` + +**Common titleText/titleId combinations:** +- "Basic [hookName] examples" / `examples-basic` +- "Examples of [concept]" / `examples-[concept]` +- "The difference between [A] and [B]" / `examples-[topic]` + +--- + +## `` + +End-of-page exercises. **Learn pages only.** Each challenge needs problem + solution Sandpack. + +```mdx + + +#### Fix the bug {/*fix-the-bug*/} + +Problem description... + + +Optional hint text. + + + +{/* problem code */} + + + + +Explanation... + + +{/* solution code */} + + + + + +``` + +**Guidelines:** +- Only at end of standard Learn pages +- No Challenges in chapter intros or tutorials +- Each challenge has `####` heading with ID + +--- + +## `` + +For deprecated APIs. Content should explain what to use instead. + +### Page-Level Deprecation + +```mdx + + +In React 19, `forwardRef` is no longer necessary. Pass `ref` as a prop instead. + +`forwardRef` will be deprecated in a future release. Learn more [here](/blog/2024/04/25/react-19#ref-as-a-prop). + + +``` + +### Method-Level Deprecation + +```mdx +### `componentWillMount()` {/*componentwillmount*/} + + + +This API has been renamed from `componentWillMount` to [`UNSAFE_componentWillMount`.](#unsafe_componentwillmount) + +Run the [`rename-unsafe-lifecycles` codemod](codemod-link) to automatically update. + + +``` + +--- + +## `` + +For APIs that only work with React Server Components. + +### Basic RSC + +```mdx + + +`cache` is only for use with [React Server Components](/reference/rsc/server-components). + + +``` + +### Extended RSC (for Server Functions) + +```mdx + + +Server Functions are for use in [React Server Components](/reference/rsc/server-components). + +**Note:** Until September 2024, we referred to all Server Functions as "Server Actions". + + +``` + +--- + +## `` and `` + +For features only available in Canary releases. + +### Canary Wrapper (inline in Intro) + +```mdx + + +`` lets you group elements without a wrapper node. + +Fragments can also accept refs, enabling interaction with underlying DOM nodes. + + +``` + +### CanaryBadge in Section Headings + +```mdx +### FragmentInstance {/*fragmentinstance*/} +``` + +### CanaryBadge in Props Lists + +```mdx +* **optional** `ref`: A ref object from `useRef` or callback function. +``` + +### CanaryBadge in Caveats + +```mdx +* If you want to pass `ref` to a Fragment, you can't use the `<>...` syntax. +``` + +--- + +## `` + +Visual explanations of module dependencies, render trees, or data flow. + +```mdx + +`'use client'` segments the module dependency tree, marking `InspirationGenerator.js` and all dependencies as client-rendered. + +``` + +**Attributes:** +- `name`: Diagram identifier (used for image file) +- `height`: Height in pixels +- `width`: Width in pixels +- `alt`: Accessible description of the diagram + +--- + +## `` (Use Sparingly) + +Numbered callouts in prose. Pairs with code block annotations. + +### Syntax + +In code blocks: +```mdx +```js [[1, 4, "age"], [2, 4, "setAge"], [3, 4, "42"]] +import { useState } from 'react'; + +function MyComponent() { + const [age, setAge] = useState(42); +} +``` +``` + +Format: `[[step_number, line_number, "text_to_highlight"], ...]` + +In prose: +```mdx +1. The current state initially set to the initial value. +2. The `set` function that lets you change it. +``` + +### Guidelines + +- Maximum 2-3 different colors per explanation +- Don't highlight every keyword - only key concepts +- Use for terms in prose, not entire code blocks +- Maintain consistent usage within a section + +βœ… **Good use** - highlighting key concepts: +```mdx +React will compare the dependencies with the dependencies you passed... +``` + +🚫 **Avoid** - excessive highlighting: +```mdx +When an Activity boundary is hidden during its initial render... +``` + +--- + +## `` + +Display console output (errors, warnings, logs). + +```mdx + +Uncaught Error: Too many re-renders. + +``` + +**Levels:** `error`, `warning`, `info` + +--- + +## Component Usage by Page Type + +### Reference Pages + +For component placement rules specific to Reference pages, invoke `/docs-writer-reference`. + +Key placement patterns: +- `` goes before `` at top of page +- `` goes after `` for page-level deprecation +- `` goes after method heading for method-level deprecation +- `` wrapper goes inline within `` +- `` appears in headings, props lists, and caveats + +### Learn Pages + +For Learn page structure and patterns, invoke `/docs-writer-learn`. + +Key usage patterns: +- Challenges only at end of standard Learn pages +- No Challenges in chapter intros or tutorials +- DeepDive for optional advanced content +- CodeStep should be used sparingly + +### Blog Pages + +For Blog page structure and patterns, invoke `/docs-writer-blog`. + +Key usage patterns: +- Generally avoid deep technical components +- Note and Pitfall OK for clarifications +- Prefer inline explanations over DeepDive + +--- + +## Other Available Components + +**Version/Status:** ``, ``, ``, ``, `` + +**Visuals:** ``, ``, ``, ``, `` + +**Console:** ``, `` + +**Specialized:** ``, ``, ``, ``, ``, ``, ``, ``, `` + +See existing docs for usage examples of these components. diff --git a/.claude/skills/docs-rsc-sandpack/SKILL.md b/.claude/skills/docs-rsc-sandpack/SKILL.md new file mode 100644 index 000000000..04f76168e --- /dev/null +++ b/.claude/skills/docs-rsc-sandpack/SKILL.md @@ -0,0 +1,277 @@ +--- +name: docs-rsc-sandpack +description: Use when adding interactive RSC (React Server Components) code examples to React docs using , or when modifying the RSC sandpack infrastructure. +--- + +# RSC Sandpack Patterns + +For general Sandpack conventions (code style, naming, file naming, line highlighting, hidden files, CSS guidelines), see `/docs-sandpack`. This skill covers only RSC-specific patterns. + +## Quick Start Template + +Minimal single-file `` example: + +```mdx + + +` ` `js src/App.js +export default function App() { + return

Hello from a Server Component!

; +} +` ` ` + + +``` + +--- + +## How It Differs from `` + +| Feature | `` | `` | +|---------|-------------|-----------------| +| Execution model | All code runs in iframe | Server code runs in Web Worker, client code in iframe | +| `'use client'` directive | Ignored (everything is client) | Required to mark client components | +| `'use server'` directive | Not supported | Marks Server Functions callable from client | +| `async` components | Not supported | Supported (server components can be async) | +| External dependencies | Supported via `package.json` | Not supported (only React + react-dom) | +| Entry point | `App.js` with `export default` | `src/App.js` with `export default` | +| Component tag | `` | `` | + +--- + +## File Directives + +Files are classified by the directive at the top of the file: + +| Directive | Where it runs | Rules | +|-----------|--------------|-------| +| (none) | Web Worker (server) | Default. Can be `async`. Can import other server files. Cannot use hooks, event handlers, or browser APIs. | +| `'use client'` | Sandpack iframe (browser) | Must be first statement. Can use hooks, event handlers, browser APIs. Cannot be `async`. Cannot import server files. | +| `'use server'` | Web Worker (server) | Marks Server Functions. Can be module-level (all exports are actions) or function-level. Callable from client via props or form `action`. | + +--- + +## Common Patterns + +### 1. Server + Client Components + +```mdx + + +` ` `js src/App.js +import Counter from './Counter'; + +export default function App() { + return ( +
+

Server-rendered heading

+ +
+ ); +} +` ` ` + +` ` `js src/Counter.js +'use client'; + +import { useState } from 'react'; + +export default function Counter() { + const [count, setCount] = useState(0); + return ( + + ); +} +` ` ` + +
+``` + +### 2. Async Server Component with Suspense + +```mdx + + +` ` `js src/App.js +import { Suspense } from 'react'; +import Albums from './Albums'; + +export default function App() { + return ( + Loading...

}> + +
+ ); +} +` ` ` + +` ` `js src/Albums.js +async function fetchAlbums() { + await new Promise(resolve => setTimeout(resolve, 1000)); + return ['Abbey Road', 'Let It Be', 'Revolver']; +} + +export default async function Albums() { + const albums = await fetchAlbums(); + return ( +
    + {albums.map(album => ( +
  • {album}
  • + ))} +
+ ); +} +` ` ` + +
+``` + +### 3. Server Functions (Actions) + +```mdx + + +` ` `js src/App.js +import { addLike, getLikeCount } from './actions'; +import LikeButton from './LikeButton'; + +export default async function App() { + const count = await getLikeCount(); + return ( +
+

Likes: {count}

+ +
+ ); +} +` ` ` + +` ` `js src/actions.js +'use server'; + +let count = 0; + +export async function addLike() { + count++; +} + +export async function getLikeCount() { + return count; +} +` ` ` + +` ` `js src/LikeButton.js +'use client'; + +export default function LikeButton({ addLike }) { + return ( + + + + ); +} +` ` ` + +
+``` + +--- + +## File Structure Requirements + +### Entry Point + +- **`src/App.js` is required** as the main entry point +- Must have `export default` (function component) +- Case-insensitive fallback: `src/app.js` also works + +### Auto-Injected Infrastructure Files + +These files are automatically injected by `sandpack-rsc-setup.ts` and should never be included in MDX: + +| File | Purpose | +|------|---------| +| `/src/index.js` | Bootstraps the RSC pipeline | +| `/src/rsc-client.js` | Client bridge β€” creates Worker, consumes Flight stream | +| `/src/rsc-server.js` | Wraps pre-bundled worker runtime as ES module | +| `/node_modules/__webpack_shim__/index.js` | Minimal webpack compatibility layer | +| `/node_modules/__rsdw_client__/index.js` | `react-server-dom-webpack/client` as local dependency | + +### No External Dependencies + +`` does not support external npm packages. Only `react` and `react-dom` are available. Do not include `package.json` in RSC examples. + +--- + +## Architecture Reference + +### Three-Layer Architecture + +``` +react.dev page (Next.js) + β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” + β”‚ β”‚ + β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ + β”‚ β”‚ Editor β”‚ β”‚ Preview (iframe) β”‚ β”‚ + β”‚ β”‚ App.js β”‚ β”‚ Client React app β”‚ β”‚ + β”‚ β”‚ (edit) β”‚ β”‚ consumes Flight β”‚ β”‚ + β”‚ β”‚ β”‚ β”‚ stream from Worker β”‚ β”‚ + β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ + β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ + β”‚ postMessage + β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” + β”‚ Web Worker (Blob URL) β”‚ + β”‚ - React server build (pre-bundled) β”‚ + β”‚ - react-server-dom-webpack/server β”‚ + β”‚ - webpack shim β”‚ + β”‚ - User server code (Sucrase β†’ CJS) β”‚ + β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ +``` + +### Key Source Files + +| File | Purpose | +|-----------------------------------------------------------------|--------------------------------------------------------------------------------| +| `src/components/MDX/Sandpack/sandpack-rsc/RscFileBridge.tsx` | Monitors Sandpack; posts raw files to iframe | +| `src/components/MDX/Sandpack/SandpackRSCRoot.tsx` | SandpackProvider setup, custom bundler URL, UI layout | +| `src/components/MDX/Sandpack/templateRSC.ts` | RSC template files | +| `.../sandbox-code/src/__react_refresh_init__.js` | React Refresh shim | +| `.../sandbox-code/src/rsc-server.js` | Worker runtime: module system, Sucrase compilation, `renderToReadableStream()` | +| `.../sandbox-code/src/rsc-client.source.js` | Client bridge: Worker creation, file classification, Flight stream consumption | +| `.../sandbox-code/src/webpack-shim.js` | Minimal `__webpack_require__` / `__webpack_module_cache__` shim | +| `.../sandbox-code/src/worker-bundle.dist.js` | Pre-bundled IIFE (generated): React server + RSDW/server + Sucrase | +| `scripts/buildRscWorker.mjs` | esbuild script: bundles rsc-server.js into worker-bundle.dist.js | + +--- + +## Build System + +### Rebuilding the Worker Bundle + +After modifying `rsc-server.js` or `webpack-shim.js`: + +```bash +node scripts/buildRscWorker.mjs +``` + +This runs esbuild with: +- `format: 'iife'`, `platform: 'browser'` +- `conditions: ['react-server', 'browser']` (activates React server export conditions) +- `minify: true` +- Prepends `webpack-shim.js` to the output + +### Raw-Loader Configuration + +In `templateRSC.js` files are loaded as raw strings with the `!raw-loader`. + +The strings are necessary to provide to Sandpack as local files (skips Sandpack bundling). + + +### Development Commands + +```bash +node scripts/buildRscWorker.mjs # Rebuild worker bundle after source changes +yarn dev # Start dev server to test examples +``` diff --git a/.claude/skills/docs-sandpack/SKILL.md b/.claude/skills/docs-sandpack/SKILL.md new file mode 100644 index 000000000..0904a98c0 --- /dev/null +++ b/.claude/skills/docs-sandpack/SKILL.md @@ -0,0 +1,447 @@ +--- +name: docs-sandpack +description: Use when adding interactive code examples to React docs. +--- + +# Sandpack Patterns + +## Quick Start Template + +Most examples are single-file. Copy this and modify: + +```mdx + + +` ` `js +import { useState } from 'react'; + +export default function Example() { + const [value, setValue] = useState(0); + + return ( + + ); +} +` ` ` + + +``` + +--- + +## File Naming + +| Pattern | Usage | +|---------|-------| +| ` ```js ` | Main file (no prefix) | +| ` ```js src/FileName.js ` | Supporting files | +| ` ```js src/File.js active ` | Active file (reference pages) | +| ` ```js src/data.js hidden ` | Hidden files | +| ` ```css ` | CSS styles | +| ` ```json package.json ` | External dependencies | + +**Critical:** Main file must have `export default`. + +## Line Highlighting + +```mdx +```js {2-4} +function Example() { + // Lines 2-4 + // will be + // highlighted + return null; +} +``` + +## Code References (numbered callouts) + +```mdx +```js [[1, 4, "age"], [2, 4, "setAge"]] +// Creates numbered markers pointing to "age" and "setAge" on line 4 +``` + +## Expected Errors (intentionally broken examples) + +```mdx +```js {expectedErrors: {'react-compiler': [7]}} +// Line 7 shows as expected error +``` + +## Multi-File Example + +```mdx + + +```js src/App.js +import Gallery from './Gallery.js'; + +export default function App() { + return ; +} +``` + +```js src/Gallery.js +export default function Gallery() { + return

Gallery

; +} +``` + +```css +h1 { color: purple; } +``` + +
+``` + +## External Dependencies + +```mdx + + +```js +import { useImmer } from 'use-immer'; +// ... +``` + +```json package.json +{ + "dependencies": { + "immer": "1.7.3", + "use-immer": "0.5.1", + "react": "latest", + "react-dom": "latest", + "react-scripts": "latest" + } +} +``` + + +``` + +## Code Style in Sandpack (Required) + +Sandpack examples are held to strict code style standards: + +1. **Function declarations** for components (not arrows) +2. **`e`** for event parameters +3. **Single quotes** in JSX +4. **`const`** unless reassignment needed +5. **Spaces in destructuring**: `({ props })` not `({props})` +6. **Two-line createRoot**: separate declaration and render call +7. **Multiline if statements**: always use braces + +### Don't Create Hydration Mismatches + +Sandpack examples must produce the same output on server and client: + +```js +// 🚫 This will cause hydration warnings +export default function App() { + const isClient = typeof window !== 'undefined'; + return
{isClient ? 'Client' : 'Server'}
; +} +``` + +### Use Ref for Non-Rendered State + +```js +// 🚫 Don't trigger re-renders for non-visual state +const [mounted, setMounted] = useState(false); +useEffect(() => { setMounted(true); }, []); + +// βœ… Use ref instead +const mounted = useRef(false); +useEffect(() => { mounted.current = true; }, []); +``` + +## forwardRef and memo Patterns + +### forwardRef - Use Named Function +```js +// βœ… Named function for DevTools display name +const MyInput = forwardRef(function MyInput(props, ref) { + return ; +}); + +// 🚫 Anonymous loses name +const MyInput = forwardRef((props, ref) => { ... }); +``` + +### memo - Use Named Function +```js +// βœ… Preserves component name +const Greeting = memo(function Greeting({ name }) { + return

Hello, {name}

; +}); +``` + +## Line Length + +- Prose: ~80 characters +- Code: ~60-70 characters +- Break long lines to avoid horizontal scrolling + +## Anti-Patterns + +| Pattern | Problem | Fix | +|---------|---------|-----| +| `const Comp = () => {}` | Not standard | `function Comp() {}` | +| `onClick={(event) => ...}` | Conflicts with global | `onClick={(e) => ...}` | +| `useState` for non-rendered values | Re-renders | Use `useRef` | +| Reading `window` during render | Hydration mismatch | Check in useEffect | +| Single-line if without braces | Harder to debug | Use multiline with braces | +| Chained `createRoot().render()` | Less clear | Two statements | +| `//...` without space | Inconsistent | `// ...` with space | +| Tabs | Inconsistent | 2 spaces | +| `ReactDOM.render` | Deprecated | Use `createRoot` | +| Fake package names | Confusing | Use `'./your-storage-layer'` | +| `PropsWithChildren` | Outdated | `children?: ReactNode` | +| Missing `key` in lists | Warnings | Always include key | + +## Additional Code Quality Rules + +### Always Include Keys in Lists +```js +// βœ… Correct +{items.map(item =>
  • {item.name}
  • )} + +// 🚫 Wrong - missing key +{items.map(item =>
  • {item.name}
  • )} +``` + +### Use Realistic Import Paths +```js +// βœ… Correct - descriptive path +import { fetchData } from './your-data-layer'; + +// 🚫 Wrong - looks like a real npm package +import { fetchData } from 'cool-data-lib'; +``` + +### Console.log Labels +```js +// βœ… Correct - labeled for clarity +console.log('User:', user); +console.log('Component Stack:', errorInfo.componentStack); + +// 🚫 Wrong - unlabeled +console.log(user); +``` + +### Keep Delays Reasonable +```js +// βœ… Correct - 1-1.5 seconds +setTimeout(() => setLoading(false), 1000); + +// 🚫 Wrong - too long, feels sluggish +setTimeout(() => setLoading(false), 3000); +``` + +## Updating Line Highlights + +When modifying code in examples with line highlights (`{2-4}`), **always update the highlight line numbers** to match the new code. Incorrect line numbers cause rendering crashes. + +## File Name Conventions + +- Capitalize file names for component files: `Gallery.js` not `gallery.js` +- After initially explaining files are in `src/`, refer to files by name only: `Gallery.js` not `src/Gallery.js` + +## Naming Conventions in Code + +**Components:** PascalCase +- `Profile`, `Avatar`, `TodoList`, `PackingList` + +**State variables:** Destructured pattern +- `const [count, setCount] = useState(0)` +- Booleans: `[isOnline, setIsOnline]`, `[isPacked, setIsPacked]` +- Status strings: `'typing'`, `'submitting'`, `'success'`, `'error'` + +**Event handlers:** +- `handleClick`, `handleSubmit`, `handleAddTask` + +**Props for callbacks:** +- `onClick`, `onChange`, `onAddTask`, `onSelect` + +**Custom Hooks:** +- `useOnlineStatus`, `useChatRoom`, `useFormInput` + +**Reducer actions:** +- Past tense: `'added'`, `'changed'`, `'deleted'` +- Snake_case compounds: `'changed_selection'`, `'sent_message'` + +**Updater functions:** Single letter +- `setCount(n => n + 1)` + +### Pedagogical Code Markers + +**Wrong vs right code:** +```js +// πŸ”΄ Avoid: redundant state and unnecessary Effect +// βœ… Good: calculated during rendering +``` + +**Console.log for lifecycle teaching:** +```js +console.log('βœ… Connecting...'); +console.log('❌ Disconnected.'); +``` + +### Server/Client Labeling + +```js +// Server Component +async function Notes() { + const notes = await db.notes.getAll(); +} + +// Client Component +"use client" +export default function Expandable({children}) { + const [expanded, setExpanded] = useState(false); +} +``` + +### Bundle Size Annotations + +```js +import marked from 'marked'; // 35.9K (11.2K gzipped) +import sanitizeHtml from 'sanitize-html'; // 206K (63.3K gzipped) +``` + +--- + +## Sandpack Example Guidelines + +### Package.json Rules + +**Include package.json when:** +- Using external npm packages (immer, remarkable, leaflet, toastify-js, etc.) +- Demonstrating experimental/canary React features +- Requiring specific React versions (`react: beta`, `react: 19.0.0-rc-*`) + +**Omit package.json when:** +- Example uses only built-in React features +- No external dependencies needed +- Teaching basic hooks, state, or components + +**Always mark package.json as hidden:** +```mdx +```json package.json hidden +{ + "dependencies": { + "react": "latest", + "react-dom": "latest", + "react-scripts": "latest", + "immer": "1.7.3" + } +} +``` +``` + +**Version conventions:** +- Use `"latest"` for stable features +- Use exact versions only when compatibility requires it +- Include minimal dependencies (just what the example needs) + +### Hidden File Patterns + +**Always hide these file types:** + +| File Type | Reason | +|-----------|--------| +| `package.json` | Configuration not the teaching point | +| `sandbox.config.json` | Sandbox setup is boilerplate | +| `public/index.html` | HTML structure not the focus | +| `src/data.js` | When it contains sample/mock data | +| `src/api.js` | When showing API usage, not implementation | +| `src/styles.css` | When styling is not the lesson | +| `src/router.js` | Supporting infrastructure | +| `src/actions.js` | Server action implementation details | + +**Rationale:** +- Reduces cognitive load +- Keeps focus on the primary concept +- Creates cleaner, more focused examples + +**Example:** +```mdx +```js src/data.js hidden +export const items = [ + { id: 1, name: 'Item 1' }, + { id: 2, name: 'Item 2' }, +]; +``` +``` + +### Active File Patterns + +**Mark as active when:** +- File contains the primary teaching concept +- Learner should focus on this code first +- Component demonstrates the hook/pattern being taught + +**Effect of the `active` marker:** +- Sets initial editor tab focus when Sandpack loads +- Signals "this is what you should study" +- Works with hidden files to create focused examples + +**Most common active file:** `src/index.js` or `src/App.js` + +**Example:** +```mdx +```js src/App.js active +// This file will be focused when example loads +export default function App() { + // ... +} +``` +``` + +### File Structure Guidelines + +| Scenario | Structure | Reason | +|----------|-----------|--------| +| Basic hook usage | Single file | Simple, focused | +| Teaching imports | 2-3 files | Shows modularity | +| Context patterns | 4-5 files | Realistic structure | +| Complex state | 3+ files | Separation of concerns | + +**Single File Examples (70% of cases):** +- Use for simple concepts +- 50-200 lines typical +- Best for: Counter, text inputs, basic hooks + +**Multi-File Examples (30% of cases):** +- Use when teaching modularity/imports +- Use for context patterns (4-5 files) +- Use when component is reused + +**File Naming:** +- Main component: `App.js` (capitalized) +- Component files: `Gallery.js`, `Button.js` (capitalized) +- Data files: `data.js` (lowercase) +- Utility files: `utils.js` (lowercase) +- Context files: `TasksContext.js` (named after what they provide) + +### Code Size Limits + +- Single file: **<200 lines** +- Multi-file total: **150-300 lines** +- Main component: **100-150 lines** +- Supporting files: **20-40 lines each** + +### CSS Guidelines + +**Always:** +- Include minimal CSS for demo interactivity +- Use semantic class names (`.panel`, `.button-primary`, `.panel-dark`) +- Support light/dark themes when showing UI concepts +- Keep CSS visible (never hidden) + +**Size Guidelines:** +- Minimal (5-10 lines): Basic button styling, spacing +- Medium (15-30 lines): Panel styling, form layouts +- Complex (40+ lines): Only for layout-focused examples diff --git a/.claude/skills/docs-voice/SKILL.md b/.claude/skills/docs-voice/SKILL.md new file mode 100644 index 000000000..124e5f048 --- /dev/null +++ b/.claude/skills/docs-voice/SKILL.md @@ -0,0 +1,137 @@ +--- +name: docs-voice +description: Use when writing any React documentation. Provides voice, tone, and style rules for all doc types. +--- + +# React Docs Voice & Style + +## Universal Rules + +- **Capitalize React terms** when referring to the React concept in headings or as standalone concepts: + - Core: Hook, Effect, State, Context, Ref, Component, Fragment + - Concurrent: Transition, Action, Suspense + - Server: Server Component, Client Component, Server Function, Server Action + - Patterns: Error Boundary + - Canary: Activity, View Transition, Transition Type + - **In prose:** Use lowercase when paired with descriptors: "state variable", "state updates", "event handler". Capitalize when the concept stands alone or in headings: "State is isolated and private" + - General usage stays lowercase: "the page transitions", "takes an action" +- **Product names:** ESLint, TypeScript, JavaScript, Next.js (not lowercase) +- **Bold** for key concepts: **state variable**, **event handler** +- **Italics** for new terms being defined: *event handlers* +- **Inline code** for APIs: `useState`, `startTransition`, `` +- **Avoid:** "simple", "easy", "just", time estimates +- Frame differences as "capabilities" not "advantages/disadvantages" +- Avoid passive voice and jargon + +## Tone by Page Type + +| Type | Tone | Example | +|------|------|---------| +| Learn | Conversational | "Here's what that looks like...", "You might be wondering..." | +| Reference | Technical | "Call `useState` at the top level...", "This Hook returns..." | +| Blog | Accurate | Focus on facts, not marketing | + +**Note:** Pitfall and DeepDive components can use slightly more conversational phrasing ("You might wonder...", "It might be tempting...") even in Reference pages, since they're explanatory asides. + +## Avoiding Jargon + +**Pattern:** Explain behavior first, then name it. + +βœ… "React waits until all code in event handlers runs before processing state updates. This is called *batching*." + +❌ "React uses batching to process state updates atomically." + +**Terms to avoid or explain:** +| Jargon | Plain Language | +|--------|----------------| +| atomic | all-or-nothing, batched together | +| idempotent | same inputs, same output | +| deterministic | predictable, same result every time | +| memoize | remember the result, skip recalculating | +| referentially transparent | (avoid - describe the behavior) | +| invariant | rule that must always be true | +| reify | (avoid - describe what's being created) | + +**Allowed technical terms in Reference pages:** +- "stale closures" - standard JS/React term, can be used in Caveats +- "stable identity" - React term for consistent object references across renders +- "reactive" - React term for values that trigger re-renders when changed +- These don't need explanation in Reference pages (readers are expected to know them) + +**Use established analogies sparinglyβ€”once when introducing a concept, not repeatedly:** + +| Concept | Analogy | +|---------|---------| +| Components/React | Kitchen (components as cooks, React as waiter) | +| Render phases | Restaurant ordering (trigger/render/commit) | +| State batching | Waiter collecting full order before going to kitchen | +| State behavior | Snapshot/photograph in time | +| State storage | React storing state "on a shelf" | +| State purpose | Component's memory | +| Pure functions | Recipes (same ingredients β†’ same dish) | +| Pure functions | Math formulas (y = 2x) | +| Props | Adjustable "knobs" | +| Children prop | "Hole" to be filled by parent | +| Keys | File names in a folder | +| Curly braces in JSX | "Window into JavaScript" | +| Declarative UI | Taxi driver (destination, not turn-by-turn) | +| Imperative UI | Turn-by-turn navigation | +| State structure | Database normalization | +| Refs | "Secret pocket" React doesn't track | +| Effects/Refs | "Escape hatch" from React | +| Context | CSS inheritance / "Teleportation" | +| Custom Hooks | Design system | + +## Common Prose Patterns + +**Wrong vs Right code:** +```mdx +\`\`\`js +// 🚩 Don't mutate state: +obj.x = 10; +\`\`\` + +\`\`\`js +// βœ… Replace with new object: +setObj({ ...obj, x: 10 }); +\`\`\` +``` + +**Table comparisons:** +```mdx +| passing a function | calling a function | +| `onClick={handleClick}` | `onClick={handleClick()}` | +``` + +**Linking:** +```mdx +[Read about state](/learn/state-a-components-memory) +[See `useState` reference](/reference/react/useState) +``` + +## Code Style + +- Prefer JSX over createElement +- Use const/let, never var +- Prefer named function declarations for top-level functions +- Arrow functions for callbacks that need `this` preservation + +## Version Documentation + +When APIs change between versions: + +```mdx +Starting in React 19, render `` as a provider: +\`\`\`js +{children} +\`\`\` + +In older versions: +\`\`\`js +{children} +\`\`\` +``` + +Patterns: +- "Starting in React 19..." for new APIs +- "In older versions of React..." for legacy patterns diff --git a/.claude/skills/docs-writer-blog/SKILL.md b/.claude/skills/docs-writer-blog/SKILL.md new file mode 100644 index 000000000..ef28225f8 --- /dev/null +++ b/.claude/skills/docs-writer-blog/SKILL.md @@ -0,0 +1,756 @@ +--- +name: docs-writer-blog +description: Use when writing or editing files in src/content/blog/. Provides blog post structure and conventions. +--- + +# Blog Post Writer + +## Persona + +**Voice:** Official React team voice +**Tone:** Accurate, professional, forward-looking + +## Voice & Style + +For tone, capitalization, jargon, and prose patterns, invoke `/docs-voice`. + +--- + +## Frontmatter Schema + +All blog posts use this YAML frontmatter structure: + +```yaml +--- +title: "Title in Quotes" +author: Author Name(s) +date: YYYY/MM/DD +description: One or two sentence summary. +--- +``` + +### Field Details + +| Field | Format | Example | +|-------|--------|---------| +| `title` | Quoted string | `"React v19"`, `"React Conf 2024 Recap"` | +| `author` | Unquoted, comma + "and" for multiple | `The React Team`, `Dan Abramov and Lauren Tan` | +| `date` | `YYYY/MM/DD` with forward slashes | `2024/12/05` | +| `description` | 1-2 sentences, often mirrors intro | Summarizes announcement or content | + +### Title Patterns by Post Type + +| Type | Pattern | Example | +|------|---------|---------| +| Release | `"React vX.Y"` or `"React X.Y"` | `"React v19"` | +| Upgrade | `"React [VERSION] Upgrade Guide"` | `"How to Upgrade to React 18"` | +| Labs | `"React Labs: [Topic] – [Month Year]"` | `"React Labs: What We've Been Working On – February 2024"` | +| Conf | `"React Conf [YEAR] Recap"` | `"React Conf 2024 Recap"` | +| Feature | `"Introducing [Feature]"` or descriptive | `"Introducing react.dev"` | +| Security | `"[Severity] Security Vulnerability in [Component]"` | `"Critical Security Vulnerability in React Server Components"` | + +--- + +## Author Byline + +Immediately after frontmatter, add a byline: + +```markdown +--- + +Month DD, YYYY by [Author Name](social-link) + +--- +``` + +### Conventions + +- Full date spelled out: `December 05, 2024` +- Team posts link to `/community/team`: `[The React Team](/community/team)` +- Individual authors link to Twitter/X or Bluesky +- Multiple authors: Oxford comma before "and" +- Followed by horizontal rule `---` + +**Examples:** + +```markdown +December 05, 2024 by [The React Team](/community/team) + +--- +``` + +```markdown +May 3, 2023 by [Dan Abramov](https://bsky.app/profile/danabra.mov), [Sophie Alpert](https://twitter.com/sophiebits), and [Andrew Clark](https://twitter.com/acdlite) + +--- +``` + +--- + +## Universal Post Structure + +All blog posts follow this structure: + +1. **Frontmatter** (YAML) +2. **Author byline** with date +3. **Horizontal rule** (`---`) +4. **`` component** (1-3 sentences) +5. **Horizontal rule** (`---`) (optional) +6. **Main content sections** (H2 with IDs) +7. **Closing section** (Changelog, Thanks, etc.) + +--- + +## Post Type Templates + +### Major Release Announcement + +```markdown +--- +title: "React vX.Y" +author: The React Team +date: YYYY/MM/DD +description: React X.Y is now available on npm! In this post, we'll give an overview of the new features. +--- + +Month DD, YYYY by [The React Team](/community/team) + +--- + + + +React vX.Y is now available on npm! + + + +In our [Upgrade Guide](/blog/YYYY/MM/DD/react-xy-upgrade-guide), we shared step-by-step instructions for upgrading. In this post, we'll give an overview of what's new. + +- [What's new in React X.Y](#whats-new) +- [Improvements](#improvements) +- [How to upgrade](#how-to-upgrade) + +--- + +## What's new in React X.Y {/*whats-new*/} + +### Feature Name {/*feature-name*/} + +[Problem this solves. Before/after code examples.] + +For more information, see the docs for [`Feature`](/reference/react/Feature). + +--- + +## Improvements in React X.Y {/*improvements*/} + +### Improvement Name {/*improvement-name*/} + +[Description of improvement.] + +--- + +## How to upgrade {/*how-to-upgrade*/} + +See [How to Upgrade to React X.Y](/blog/YYYY/MM/DD/react-xy-upgrade-guide) for step-by-step instructions. + +--- + +## Changelog {/*changelog*/} + +### React {/*react*/} + +* Add `useNewHook` for [purpose]. ([#12345](https://github.com/facebook/react/pull/12345) by [@contributor](https://github.com/contributor)) + +--- + +_Thanks to [Name](url) for reviewing this post._ +``` + +### Upgrade Guide + +```markdown +--- +title: "React [VERSION] Upgrade Guide" +author: Author Name +date: YYYY/MM/DD +description: Step-by-step instructions for upgrading to React [VERSION]. +--- + +Month DD, YYYY by [Author Name](social-url) + +--- + + + +[Summary of upgrade and what this guide covers.] + + + + + +#### Stepping stone version {/*stepping-stone*/} + +[If applicable, describe intermediate upgrade steps.] + + + +In this post, we will guide you through the steps for upgrading: + +- [Installing](#installing) +- [Codemods](#codemods) +- [Breaking changes](#breaking-changes) +- [New deprecations](#new-deprecations) + +--- + +## Installing {/*installing*/} + +```bash +npm install --save-exact react@^X.Y.Z react-dom@^X.Y.Z +``` + +## Codemods {/*codemods*/} + + + +#### Run all React [VERSION] codemods {/*run-all-codemods*/} + +```bash +npx codemod@latest react/[VERSION]/migration-recipe +``` + + + +## Breaking changes {/*breaking-changes*/} + +### Removed: `apiName` {/*removed-api-name*/} + +`apiName` was deprecated in [Month YYYY (vX.X.X)](link). + +```js +// Before +[old code] + +// After +[new code] +``` + + + +Codemod [description]: + +```bash +npx codemod@latest react/[VERSION]/codemod-name +``` + + + +## New deprecations {/*new-deprecations*/} + +### Deprecated: `apiName` {/*deprecated-api-name*/} + +[Explanation and migration path.] + +--- + +Thanks to [Contributor](link) for reviewing this post. +``` + +### React Labs Research Update + +```markdown +--- +title: "React Labs: What We've Been Working On – [Month Year]" +author: Author1, Author2, and Author3 +date: YYYY/MM/DD +description: In React Labs posts, we write about projects in active research and development. +--- + +Month DD, YYYY by [Author1](url), [Author2](url), and [Author3](url) + +--- + + + +In React Labs posts, we write about projects in active research and development. We've made significant progress since our [last update](/blog/previous-labs-post), and we'd like to share our progress. + + + +[Optional: Roadmap disclaimer about timelines] + +--- + +## Feature Name {/*feature-name*/} + + + +`` is now available in React's Canary channel. + + + +[Description of feature, motivation, current status.] + +### Subsection {/*subsection*/} + +[Details, examples, use cases.] + +--- + +## Research Area {/*research-area*/} + +[Problem space description. Status communication.] + +This research is still early. We'll share more when we're further along. + +--- + +_Thanks to [Reviewer](url) for reviewing this post._ + +Thanks for reading, and see you in the next update! +``` + +### React Conf Recap + +```markdown +--- +title: "React Conf [YEAR] Recap" +author: Author1 and Author2 +date: YYYY/MM/DD +description: Last week we hosted React Conf [YEAR]. In this post, we'll summarize the talks and announcements. +--- + +Month DD, YYYY by [Author1](url) and [Author2](url) + +--- + + + +Last week we hosted React Conf [YEAR] [where we announced [key announcements]]. + + + +--- + +The entire [day 1](youtube-url) and [day 2](youtube-url) streams are available online. + +## Day 1 {/*day-1*/} + +_[Watch the full day 1 stream here.](youtube-url)_ + +[Description of day 1 opening and keynote highlights.] + +Watch the full day 1 keynote here: + + + +## Day 2 {/*day-2*/} + +_[Watch the full day 2 stream here.](youtube-url)_ + +[Day 2 summary.] + + + +## Q&A {/*q-and-a*/} + +* [Q&A Title](youtube-url) hosted by [Host](url) + +## And more... {/*and-more*/} + +We also heard talks including: +* [Talk Title](youtube-url) by [Speaker](url) + +## Thank you {/*thank-you*/} + +Thank you to all the staff, speakers, and participants who made React Conf [YEAR] possible. + +See you next time! +``` + +### Feature/Tool Announcement + +```markdown +--- +title: "Introducing [Feature Name]" +author: Author Name +date: YYYY/MM/DD +description: Today we are announcing [feature]. In this post, we'll explain [what this post covers]. +--- + +Month DD, YYYY by [Author Name](url) + +--- + + + +Today we are [excited/thrilled] to announce [feature]. [What this means for users.] + + + +--- + +## tl;dr {/*tldr*/} + +* Key announcement point with [relevant link](/path). +* What users can do now. +* Availability or adoption information. + +## What is [Feature]? {/*what-is-feature*/} + +[Explanation of the feature/tool.] + +## Why we built this {/*why-we-built-this*/} + +[Motivation, history, problem being solved.] + +## Getting started {/*getting-started*/} + +To install [feature]: + + +npm install package-name + + +[You can find more documentation here.](/path/to/docs) + +## What's next {/*whats-next*/} + +[Future plans and next steps.] + +## Thank you {/*thank-you*/} + +[Acknowledgments to contributors.] + +--- + +Thanks to [Reviewer](url) for reviewing this post. +``` + +### Security Announcement + +```markdown +--- +title: "[Severity] Security Vulnerability in [Component]" +author: The React Team +date: YYYY/MM/DD +description: Brief summary of the vulnerability. A fix has been published. We recommend upgrading immediately. + +--- + +Month DD, YYYY by [The React Team](/community/team) + +--- + + + +[One or two sentences summarizing the vulnerability.] + +We recommend upgrading immediately. + + + +--- + +On [date], [researcher] reported a security vulnerability that allows [description]. + +This vulnerability was disclosed as [CVE-YYYY-NNNNN](https://www.cve.org/CVERecord?id=CVE-YYYY-NNNNN) and is rated CVSS [score]. + +The vulnerability is present in versions [list] of: + +* [package-name](https://www.npmjs.com/package/package-name) + +## Immediate Action Required {/*immediate-action-required*/} + +A fix was introduced in versions [linked versions]. Upgrade immediately. + +### Affected frameworks {/*affected-frameworks*/} + +[List of affected frameworks with npm links.] + +### Vulnerability overview {/*vulnerability-overview*/} + +[Technical explanation of the vulnerability.] + +## Update Instructions {/*update-instructions*/} + +### Framework Name {/*update-framework-name*/} + +```bash +npm install package@version +``` + +## Timeline {/*timeline*/} + +* **November 29th**: [Researcher] reported the vulnerability. +* **December 1st**: Fix was created and validated. +* **December 3rd**: Fix published and CVE disclosed. + +## Attribution {/*attribution*/} + +Thank you to [Researcher Name](url) for discovering and reporting this vulnerability. +``` + +--- + +## Heading Conventions + +### ID Syntax + +All headings require IDs using CSS comment syntax: + +```markdown +## Heading Text {/*heading-id*/} +``` + +### ID Rules + +- Lowercase +- Kebab-case (hyphens for spaces) +- Remove special characters (apostrophes, colons, backticks) +- Concise but descriptive + +### Heading Patterns + +| Context | Example | +|---------|---------| +| Feature section | `## New Feature: Automatic Batching {/*new-feature-automatic-batching*/}` | +| New hook | `### New hook: \`useActionState\` {/*new-hook-useactionstate*/}` | +| API in backticks | `### \`\` {/*activity*/}` | +| Removed API | `#### Removed: \`propTypes\` {/*removed-proptypes*/}` | +| tl;dr section | `## tl;dr {/*tldr*/}` | + +--- + +## Component Usage Guide + +### Blog-Appropriate Components + +| Component | Usage in Blog | +|-----------|---------------| +| `` | **Required** - Opening summary after byline | +| `` | Callouts, caveats, important clarifications | +| `` | Warnings about common mistakes | +| `` | Optional technical deep dives (use sparingly) | +| `` | CLI/installation commands | +| `` | Console error/warning output | +| `` | Multi-line console output | +| `` | Conference video embeds | +| `` | Visual explanations | +| `` | Auto-generated table of contents | + +### `` Pattern + +Always wrap opening paragraph: + +```markdown + + +React 19 is now available on npm! + + +``` + +### `` Patterns + +**Simple note:** +```markdown + + +For React Native users, React 18 ships with the New Architecture. + + +``` + +**Titled note (H4 inside):** +```markdown + + +#### React 18.3 has also been published {/*react-18-3*/} + +To help with the upgrade, we've published `react@18.3`... + + +``` + +### `` Pattern + +```markdown + +npm install react@latest react-dom@latest + +``` + +### `` Pattern + +```markdown + +``` + +--- + +## Link Patterns + +### Internal Links + +| Type | Pattern | Example | +|------|---------|---------| +| Blog post | `/blog/YYYY/MM/DD/slug` | `/blog/2024/12/05/react-19` | +| API reference | `/reference/react/HookName` | `/reference/react/useState` | +| Learn section | `/learn/topic-name` | `/learn/react-compiler` | +| Community | `/community/team` | `/community/team` | + +### External Links + +| Type | Pattern | +|------|---------| +| GitHub PR | `[#12345](https://github.com/facebook/react/pull/12345)` | +| GitHub user | `[@username](https://github.com/username)` | +| Twitter/X | `[@username](https://x.com/username)` | +| Bluesky | `[Name](https://bsky.app/profile/handle)` | +| CVE | `[CVE-YYYY-NNNNN](https://www.cve.org/CVERecord?id=CVE-YYYY-NNNNN)` | +| npm package | `[package](https://www.npmjs.com/package/package)` | + +### "See docs" Pattern + +```markdown +For more information, see the docs for [`useActionState`](/reference/react/useActionState). +``` + +--- + +## Changelog Format + +### Bullet Pattern + +```markdown +* Add `useTransition` for concurrent rendering. ([#10426](https://github.com/facebook/react/pull/10426) by [@acdlite](https://github.com/acdlite)) +* Fix `useReducer` observing incorrect props. ([#22445](https://github.com/facebook/react/pull/22445) by [@josephsavona](https://github.com/josephsavona)) +``` + +**Structure:** `Verb` + backticked API + description + `([#PR](url) by [@user](url))` + +**Verbs:** Add, Fix, Remove, Make, Improve, Allow, Deprecate + +### Section Organization + +```markdown +## Changelog {/*changelog*/} + +### React {/*react*/} + +* [changes] + +### React DOM {/*react-dom*/} + +* [changes] +``` + +--- + +## Acknowledgments Format + +### Post-closing Thanks + +```markdown +--- + +Thanks to [Name](url), [Name](url), and [Name](url) for reviewing this post. +``` + +Or italicized: + +```markdown +_Thanks to [Name](url) for reviewing this post._ +``` + +### Update Notes + +For post-publication updates: + +```markdown + + +[Updated content] + +----- + +_Updated January 26, 2026._ + + +``` + +--- + +## Tone & Length by Post Type + +| Type | Tone | Length | Key Elements | +|------|------|--------|--------------| +| Release | Celebratory, informative | Medium-long | Feature overview, upgrade link, changelog | +| Upgrade | Instructional, precise | Long | Step-by-step, codemods, breaking changes | +| Labs | Transparent, exploratory | Medium | Status updates, roadmap disclaimers | +| Conf | Enthusiastic, community-focused | Medium | YouTube embeds, speaker credits | +| Feature | Excited, explanatory | Medium | tl;dr, "why", getting started | +| Security | Urgent, factual | Short-medium | Immediate action, timeline, CVE | + +--- + +## Do's and Don'ts + +**Do:** +- Focus on facts over marketing +- Say "upcoming" explicitly for unreleased features +- Include FAQ sections for major announcements +- Credit contributors and link to GitHub +- Use "we" voice for team posts +- Link to upgrade guides from release posts +- Include table of contents for long posts +- End with acknowledgments + +**Don't:** +- Promise features not yet available +- Rewrite history (add update notes instead) +- Break existing URLs +- Use hyperbolic language ("revolutionary", "game-changing") +- Skip the `` component +- Forget heading IDs +- Use heavy component nesting in blogs +- Make time estimates or predictions + +--- + +## Updating Old Posts + +- Never break existing URLs; add redirects when URLs change +- Don't rewrite history; add update notes instead: + ```markdown + + + [Updated information] + + ----- + + _Updated Month Year._ + + + ``` + +--- + +## Critical Rules + +1. **Heading IDs required:** `## Title {/*title-id*/}` +2. **`` required:** Every post starts with `` component +3. **Byline required:** Date + linked author(s) after frontmatter +4. **Date format:** Frontmatter uses `YYYY/MM/DD`, byline uses `Month DD, YYYY` +5. **Link to docs:** New APIs must link to reference documentation +6. **Security posts:** Always include "We recommend upgrading immediately" + +--- + +## Components Reference + +For complete MDX component patterns, invoke `/docs-components`. + +Blog posts commonly use: ``, ``, ``, ``, ``, ``, ``, ``. + +Prefer inline explanations over heavy component usage. diff --git a/.claude/skills/docs-writer-learn/SKILL.md b/.claude/skills/docs-writer-learn/SKILL.md new file mode 100644 index 000000000..57dc9ef74 --- /dev/null +++ b/.claude/skills/docs-writer-learn/SKILL.md @@ -0,0 +1,299 @@ +--- +name: docs-writer-learn +description: Use when writing or editing files in src/content/learn/. Provides Learn page structure and tone. +--- + +# Learn Page Writer + +## Persona + +**Voice:** Patient teacher guiding a friend through concepts +**Tone:** Conversational, warm, encouraging + +## Voice & Style + +For tone, capitalization, jargon, and prose patterns, invoke `/docs-voice`. + +## Page Structure Variants + +### 1. Standard Learn Page (Most Common) + +```mdx +--- +title: Page Title +--- + + +1-3 sentences introducing the concept. Use *italics* for new terms. + + + + +* Learning outcome 1 +* Learning outcome 2 +* Learning outcome 3-5 + + + +## Section Name {/*section-id*/} + +Content with Sandpack examples, Pitfalls, Notes, DeepDives... + +## Another Section {/*another-section*/} + +More content... + + + +* Summary point 1 +* Summary point 2 +* Summary points 3-9 + + + + + +#### Challenge title {/*challenge-id*/} + +Description... + + +Optional guidance (single paragraph) + + + +{/* Starting code */} + + + +Explanation... + + +{/* Fixed code */} + + + + +``` + +### 2. Chapter Introduction Page + +For pages that introduce a chapter (like describing-the-ui.md, managing-state.md): + +```mdx + + +* [Sub-page title](/learn/sub-page-name) to learn... +* [Another page](/learn/another-page) to learn... + + + +## Preview Section {/*section-id*/} + +Preview description with mini Sandpack example + + + +Read **[Page Title](/learn/sub-page-name)** to learn how to... + + + +## What's next? {/*whats-next*/} + +Head over to [First Page](/learn/first-page) to start reading this chapter page by page! +``` + +**Important:** Chapter intro pages do NOT include `` or `` sections. + +### 3. Tutorial Page + +For step-by-step tutorials (like tutorial-tic-tac-toe.md): + +```mdx + +Brief statement of what will be built + + + +Alternative learning path offered + + +Table of contents (prose listing of major sections) + +## Setup {/*setup*/} +... + +## Main Content {/*main-content*/} +Progressive code building with ### subsections + +No YouWillLearn, Recap, or Challenges + +Ends with ordered list of "extra credit" improvements +``` + +### 4. Reference-Style Learn Page + +For pages with heavy API documentation (like typescript.md): + +```mdx + + +* [Link to section](#section-anchor) +* [Link to another section](#another-section) + + + +## Sections with ### subsections + +## Further learning {/*further-learning*/} + +No Recap or Challenges +``` + +## Heading ID Conventions + +All headings require IDs in `{/*kebab-case*/}` format: + +```markdown +## Section Title {/*section-title*/} +### Subsection Title {/*subsection-title*/} +#### DeepDive Title {/*deepdive-title*/} +``` + +**ID Generation Rules:** +- Lowercase everything +- Replace spaces with hyphens +- Remove apostrophes, quotes +- Remove or convert special chars (`:`, `?`, `!`, `.`, parentheses) + +**Examples:** +- "What's React?" β†’ `{/*whats-react*/}` +- "Step 1: Create the context" β†’ `{/*step-1-create-the-context*/}` +- "Conditional (ternary) operator (? :)" β†’ `{/*conditional-ternary-operator--*/}` + +## Teaching Patterns + +### Problem-First Teaching + +Show broken/problematic code BEFORE the solution: + +1. Present problematic approach with `// πŸ”΄ Avoid:` comment +2. Explain WHY it's wrong (don't just say it is) +3. Show the solution with `// βœ… Good:` comment +4. Invite experimentation + +### Progressive Complexity + +Build understanding in layers: +1. Show simplest working version +2. Identify limitation or repetition +3. Introduce solution incrementally +4. Show complete solution +5. Invite experimentation: "Try changing..." + +### Numbered Step Patterns + +For multi-step processes: + +**As section headings:** +```markdown +### Step 1: Action to take {/*step-1-action*/} +### Step 2: Next action {/*step-2-next-action*/} +``` + +**As inline lists:** +```markdown +To implement this: +1. **Declare** `inputRef` with the `useRef` Hook. +2. **Pass it** as ``. +3. **Read** the input DOM node from `inputRef.current`. +``` + +### Interactive Invitations + +After Sandpack examples, encourage experimentation: +- "Try changing X to Y. See how...?" +- "Try it in the sandbox above!" +- "Click each button separately:" +- "Have a guess!" +- "Verify that..." + +### Decision Questions + +Help readers build intuition: +> "When you're not sure whether some code should be in an Effect or in an event handler, ask yourself *why* this code needs to run." + +## Component Placement Order + +1. `` - First after frontmatter +2. `` - After Intro (standard/chapter pages) +3. Body content with ``, ``, `` placed contextually +4. `` - Before Challenges (standard pages only) +5. `` - End of page (standard pages only) + +For component structure and syntax, invoke `/docs-components`. + +## Code Examples + +For Sandpack file structure, naming conventions, code style, and pedagogical markers, invoke `/docs-sandpack`. + +## Cross-Referencing + +### When to Link + +**Link to /learn:** +- Explaining concepts or mental models +- Teaching how things work together +- Tutorials and guides +- "Why" questions + +**Link to /reference:** +- API details, Hook signatures +- Parameter lists and return values +- Rules and restrictions +- "What exactly" questions + +### Link Formats + +```markdown +[concept name](/learn/page-name) +[`useState`](/reference/react/useState) +[section link](/learn/page-name#section-id) +[MDN](https://developer.mozilla.org/...) +``` + +## Section Dividers + +**Important:** Learn pages typically do NOT use `---` dividers. The heading hierarchy provides sufficient structure. Only consider dividers in exceptional cases like separating main content from meta/contribution sections. + +## Do's and Don'ts + +**Do:** +- Use "you" to address the reader +- Show broken code before fixes +- Explain behavior before naming concepts +- Build concepts progressively +- Include interactive Sandpack examples +- Use established analogies consistently +- Place Pitfalls AFTER explaining concepts +- Invite experimentation with "Try..." phrases + +**Don't:** +- Use "simple", "easy", "just", or time estimates +- Reference concepts not yet introduced +- Skip required components for page type +- Use passive voice without reason +- Place Pitfalls before teaching the concept +- Use `---` dividers between sections +- Create unnecessary abstraction in examples +- Place consecutive Pitfalls or Notes without separating prose (combine or separate) + +## Critical Rules + +1. **All headings require IDs:** `## Title {/*title-id*/}` +2. **Chapter intros use `isChapter={true}` and ``** +3. **Tutorial pages omit YouWillLearn/Recap/Challenges** +4. **Problem-first teaching:** Show broken β†’ explain β†’ fix +5. **No consecutive Pitfalls/Notes:** See `/docs-components` Callout Spacing Rules + +For component patterns, invoke `/docs-components`. For Sandpack patterns, invoke `/docs-sandpack`. diff --git a/.claude/skills/docs-writer-reference/SKILL.md b/.claude/skills/docs-writer-reference/SKILL.md new file mode 100644 index 000000000..89e087c72 --- /dev/null +++ b/.claude/skills/docs-writer-reference/SKILL.md @@ -0,0 +1,885 @@ +--- +name: docs-writer-reference +description: Reference page structure, templates, and writing patterns for src/content/reference/. For components, see /docs-components. For code examples, see /docs-sandpack. +--- + +# Reference Page Writer + +## Quick Reference + +### Page Type Decision Tree + +1. Is it a Hook? Use **Type A (Hook/Function)** +2. Is it a React component (``)? Use **Type B (Component)** +3. Is it a compiler configuration option? Use **Type C (Configuration)** +4. Is it a directive (`'use something'`)? Use **Type D (Directive)** +5. Is it an ESLint rule? Use **Type E (ESLint Rule)** +6. Is it listing multiple APIs? Use **Type F (Index/Category)** + +### Component Selection + +For component selection and patterns, invoke `/docs-components`. + +--- + +## Voice & Style + +**Voice:** Authoritative technical reference writer +**Tone:** Precise, comprehensive, neutral + +For tone, capitalization, jargon, and prose patterns, invoke `/docs-voice`. + +**Do:** +- Start with single-line description: "`useState` is a React Hook that lets you..." +- Include Parameters, Returns, Caveats sections for every API +- Document edge cases most developers will encounter +- Use section dividers between major sections +- Include "See more examples below" links +- Be assertive, not hedging - "This is designed for..." not "This helps avoid issues with..." +- State facts, not benefits - "The callback always accesses the latest values" not "This helps avoid stale closures" +- Use minimal but meaningful names - `onEvent` or `onTick` over `onSomething` + +**Don't:** +- Skip the InlineToc component +- Omit error cases or caveats +- Use conversational language +- Mix teaching with reference (that's Learn's job) +- Document past bugs or fixed issues +- Include niche edge cases (e.g., `this` binding, rare class patterns) +- Add phrases explaining "why you'd want this" - the Usage section examples do that +- Exception: Pitfall and DeepDive asides can use slightly conversational phrasing + +--- + +## Page Templates + +### Type A: Hook/Function + +**When to use:** Documenting React hooks and standalone functions (useState, useEffect, memo, lazy, etc.) + +```mdx +--- +title: hookName +--- + + + +`hookName` is a React Hook that lets you [brief description]. + +```js +const result = hookName(arg) +``` + + + + + +--- + +## Reference {/*reference*/} + +### `hookName(arg)` {/*hookname*/} + +Call `hookName` at the top level of your component to... + +```js +[signature example with annotations] +``` + +[See more examples below.](#usage) + +#### Parameters {/*parameters*/} +* `arg`: Description of the parameter. + +#### Returns {/*returns*/} +Description of return value. + +#### Caveats {/*caveats*/} +* Important caveat about usage. + +--- + +## Usage {/*usage*/} + +### Common Use Case {/*common-use-case*/} +Explanation with Sandpack examples... + +--- + +## Troubleshooting {/*troubleshooting*/} + +### Common Problem {/*common-problem*/} +How to solve it... +``` + +--- + +### Type B: Component + +**When to use:** Documenting React components (Suspense, Fragment, Activity, StrictMode) + +```mdx +--- +title: +--- + + + +`` lets you [primary action]. + +```js + + + +``` + + + + + +--- + +## Reference {/*reference*/} + +### `` {/*componentname*/} + +[Component purpose and behavior] + +#### Props {/*props*/} + +* `propName`: Description of the prop... +* **optional** `optionalProp`: Description... + +#### Caveats {/*caveats*/} + +* [Caveats specific to this component] +``` + +**Key differences from Hook pages:** +- Title uses JSX syntax: `` +- Uses `#### Props` instead of `#### Parameters` +- Reference heading uses JSX: `` ### `` `` + +--- + +### Type C: Configuration + +**When to use:** Documenting React Compiler configuration options + +```mdx +--- +title: optionName +--- + + + +The `optionName` option [controls/specifies/determines] [what it does]. + + + +```js +{ + optionName: 'value' // Quick example +} +``` + + + +--- + +## Reference {/*reference*/} + +### `optionName` {/*optionname*/} + +[Description of the option's purpose] + +#### Type {/*type*/} + +``` +'value1' | 'value2' | 'value3' +``` + +#### Default value {/*default-value*/} + +`'value1'` + +#### Options {/*options*/} + +- **`'value1'`** (default): Description +- **`'value2'`**: Description +- **`'value3'`**: Description + +#### Caveats {/*caveats*/} + +* [Usage caveats] +``` + +--- + +### Type D: Directive + +**When to use:** Documenting directives like 'use server', 'use client', 'use memo' + +```mdx +--- +title: "'use directive'" +titleForTitleTag: "'use directive' directive" +--- + + + +`'use directive'` is for use with [React Server Components](/reference/rsc/server-components). + + + + + +`'use directive'` marks [what it marks] for [purpose]. + +```js {1} +function MyComponent() { + 'use directive'; + // ... +} +``` + + + + + +--- + +## Reference {/*reference*/} + +### `'use directive'` {/*use-directive*/} + +Add `'use directive'` at the beginning of [location] to [action]. + +#### Caveats {/*caveats*/} + +* `'use directive'` must be at the very beginning... +* The directive must be written with single or double quotes, not backticks. +* [Other placement/syntax caveats] +``` + +**Key characteristics:** +- Title includes quotes: `title: "'use server'"` +- Uses `titleForTitleTag` for browser tab title +- `` block appears before `` +- Caveats focus on placement and syntax requirements + +--- + +### Type E: ESLint Rule + +**When to use:** Documenting ESLint plugin rules + +```mdx +--- +title: rule-name +--- + + +Validates that [what the rule checks]. + + +## Rule Details {/*rule-details*/} + +[Explanation of why this rule exists and React's underlying assumptions] + +## Common Violations {/*common-violations*/} + +[Description of violation patterns] + +### Invalid {/*invalid*/} + +Examples of incorrect code for this rule: + +```js +// X Missing dependency +useEffect(() => { + console.log(count); +}, []); // Missing 'count' +``` + +### Valid {/*valid*/} + +Examples of correct code for this rule: + +```js +// checkmark All dependencies included +useEffect(() => { + console.log(count); +}, [count]); +``` + +## Troubleshooting {/*troubleshooting*/} + +### [Problem description] {/*problem-slug*/} + +[Solution] + +## Options {/*options*/} + +[Configuration options if applicable] +``` + +**Key characteristics:** +- Intro is a single "Validates that..." sentence +- Uses "Invalid"/"Valid" sections with emoji-prefixed code comments +- Rule Details explains "why" not just "what" + +--- + +### Type F: Index/Category + +**When to use:** Overview pages listing multiple APIs in a category + +```mdx +--- +title: "Built-in React [Type]" +--- + + + +*Concept* let you [purpose]. Brief scope statement. + + + +--- + +## Category Name {/*category-name*/} + +*Concept* explanation with [Learn section link](/learn/topic). + +To [action], use one of these [Type]: + +* [`apiName`](/reference/react/apiName) lets you [action]. +* [`apiName`](/reference/react/apiName) declares [thing]. + +```js +function Example() { + const value = useHookName(args); +} +``` + +--- + +## Your own [Type] {/*your-own-type*/} + +You can also [define your own](/learn/topic) as JavaScript functions. +``` + +**Key characteristics:** +- Title format: "Built-in React [Type]" +- Italicized concept definitions +- Horizontal rules between sections +- Closes with "Your own [Type]" section + +--- + +## Advanced Patterns + +### Multi-Function Documentation + +**When to use:** When a hook returns a function that needs its own documentation (useState's setter, useReducer's dispatch) + +```md +### `hookName(args)` {/*hookname*/} + +[Main hook documentation] + +#### Parameters {/*parameters*/} +#### Returns {/*returns*/} +#### Caveats {/*caveats*/} + +--- + +### `set` functions, like `setSomething(nextState)` {/*setstate*/} + +The `set` function returned by `hookName` lets you [action]. + +#### Parameters {/*setstate-parameters*/} +#### Returns {/*setstate-returns*/} +#### Caveats {/*setstate-caveats*/} +``` + +**Key conventions:** +- Horizontal rule (`---`) separates main hook from returned function +- Heading IDs include prefix: `{/*setstate-parameters*/}` vs `{/*parameters*/}` +- Use generic names: "set functions" not "setCount" + +--- + +### Compound Return Objects + +**When to use:** When a function returns an object with multiple properties/methods (createContext) + +```md +### `createContext(defaultValue)` {/*createcontext*/} + +[Main function documentation] + +#### Returns {/*returns*/} + +`createContext` returns a context object. + +**The context object itself does not hold any information.** It represents... + +* `SomeContext` lets you provide the context value. +* `SomeContext.Consumer` is an alternative way to read context. + +--- + +### `SomeContext` Provider {/*provider*/} + +[Documentation for Provider] + +#### Props {/*provider-props*/} + +--- + +### `SomeContext.Consumer` {/*consumer*/} + +[Documentation for Consumer] + +#### Props {/*consumer-props*/} +``` + +--- + +## Writing Patterns + +### Opening Lines by Page Type + +| Page Type | Pattern | Example | +|-----------|---------|---------| +| Hook | `` `hookName` is a React Hook that lets you [action]. `` | "`useState` is a React Hook that lets you add a state variable to your component." | +| Component | `` `` lets you [action]. `` | "`` lets you display a fallback until its children have finished loading." | +| API | `` `apiName` lets you [action]. `` | "`memo` lets you skip re-rendering a component when its props are unchanged." | +| Configuration | `` The `optionName` option [controls/specifies/determines] [what]. `` | "The `target` option specifies which React version the compiler generates code for." | +| Directive | `` `'directive'` [marks/opts/prevents] [what] for [purpose]. `` | "`'use server'` marks a function as callable from the client." | +| ESLint Rule | `` Validates that [condition]. `` | "Validates that dependency arrays for React hooks contain all necessary dependencies." | + +--- + +### Parameter Patterns + +**Simple parameter:** +```md +* `paramName`: Description of what it does. +``` + +**Optional parameter:** +```md +* **optional** `paramName`: Description of what it does. +``` + +**Parameter with special function behavior:** +```md +* `initialState`: The value you want the state to be initially. It can be a value of any type, but there is a special behavior for functions. This argument is ignored after the initial render. + * If you pass a function as `initialState`, it will be treated as an _initializer function_. It should be pure, should take no arguments, and should return a value of any type. +``` + +**Callback parameter with sub-parameters:** +```md +* `subscribe`: A function that takes a single `callback` argument and subscribes it to the store. When the store changes, it should invoke the provided `callback`. The `subscribe` function should return a function that cleans up the subscription. +``` + +**Nested options object:** +```md +* **optional** `options`: An object with options for this React root. + * **optional** `onCaughtError`: Callback called when React catches an error in an Error Boundary. + * **optional** `onUncaughtError`: Callback called when an error is thrown and not caught. + * **optional** `identifierPrefix`: A string prefix React uses for IDs generated by `useId`. +``` + +--- + +### Return Value Patterns + +**Single value return:** +```md +`hookName` returns the current value. The value will be the same as `initialValue` during the first render. +``` + +**Array return (numbered list):** +```md +`useState` returns an array with exactly two values: + +1. The current state. During the first render, it will match the `initialState` you have passed. +2. The [`set` function](#setstate) that lets you update the state to a different value and trigger a re-render. +``` + +**Object return (bulleted list):** +```md +`createElement` returns a React element object with a few properties: + +* `type`: The `type` you have passed. +* `props`: The `props` you have passed except for `ref` and `key`. +* `ref`: The `ref` you have passed. If missing, `null`. +* `key`: The `key` you have passed, coerced to a string. If missing, `null`. +``` + +**Promise return:** +```md +`prerender` returns a Promise: +- If rendering is successful, the Promise will resolve to an object containing: + - `prelude`: a [Web Stream](MDN-link) of HTML. + - `postponed`: a JSON-serializable object for resumption. +- If rendering fails, the Promise will be rejected. +``` + +**Wrapped function return:** +```md +`cache` returns a cached version of `fn` with the same type signature. It does not call `fn` in the process. + +When calling `cachedFn` with given arguments, it first checks if a cached result exists. If cached, it returns the result. If not, it calls `fn`, stores the result, and returns it. +``` + +--- + +### Caveats Patterns + +**Standard Hook caveat (almost always first for Hooks):** +```md +* `useXxx` is a Hook, so you can only call it **at the top level of your component** or your own Hooks. You can't call it inside loops or conditions. If you need that, extract a new component and move the state into it. +``` + +**Stable identity caveat (for returned functions):** +```md +* The `set` function has a stable identity, so you will often see it omitted from Effect dependencies, but including it will not cause the Effect to fire. +``` + +**Strict Mode caveat:** +```md +* In Strict Mode, React will **call your render function twice** in order to help you find accidental impurities. This is development-only behavior and does not affect production. +``` + +**Caveat with code example:** +```md +* It's not recommended to _suspend_ a render based on a store value returned by `useSyncExternalStore`. For example, the following is discouraged: + + ```js + const selectedProductId = useSyncExternalStore(...); + const data = use(fetchItem(selectedProductId)) // X Don't suspend based on store value + ``` +``` + +**Canary caveat:** +```md +* If you want to pass `ref` to a Fragment, you can't use the `<>...` syntax. +``` + +--- + +### Troubleshooting Patterns + +**Heading format (first person problem statements):** +```md +### I've updated the state, but logging gives me the old value {/*old-value*/} + +### My initializer or updater function runs twice {/*runs-twice*/} + +### I want to read the latest state from a callback {/*read-latest-state*/} +``` + +**Error message format:** +```md +### I'm getting an error: "Too many re-renders" {/*too-many-rerenders*/} + +### I'm getting an error: "Rendered more hooks than during the previous render" {/*more-hooks*/} +``` + +**Lint error format:** +```md +### I'm getting a lint error: "[exact error message]" {/*lint-error-slug*/} +``` + +**Problem-solution structure:** +1. State the problem with code showing the issue +2. Explain why it happens +3. Provide the solution with corrected code +4. Link to Learn section for deeper understanding + +--- + +### Code Comment Conventions + +For code comment conventions (wrong/right, legacy/recommended, server/client labeling, bundle size annotations), invoke `/docs-sandpack`. + +--- + +### Link Description Patterns + +| Pattern | Example | +|---------|---------| +| "lets you" + action | "`memo` lets you skip re-rendering when props are unchanged." | +| "declares" + thing | "`useState` declares a state variable that you can update directly." | +| "reads" + thing | "`useContext` reads and subscribes to a context." | +| "connects" + thing | "`useEffect` connects a component to an external system." | +| "Used with" | "Used with [`useContext`.](/reference/react/useContext)" | +| "Similar to" | "Similar to [`useTransition`.](/reference/react/useTransition)" | + +--- + +## Component Patterns + +For comprehensive MDX component patterns (Note, Pitfall, DeepDive, Recipes, Deprecated, RSC, Canary, Diagram, Code Steps), invoke `/docs-components`. + +For Sandpack-specific patterns and code style, invoke `/docs-sandpack`. + +### Reference-Specific Component Rules + +**Component placement in Reference pages:** +- `` goes before `` at top of page +- `` goes after `` for page-level deprecation +- `` goes after method heading for method-level deprecation +- `` wrapper goes inline within `` +- `` appears in headings, props lists, and caveats + +**Troubleshooting-specific components:** +- Use first-person problem headings +- Cross-reference Pitfall IDs when relevant + +**Callout spacing:** +- Never place consecutive Pitfalls or consecutive Notes +- Combine related warnings into one with titled subsections, or separate with prose/code +- Consecutive DeepDives OK for multi-part explorations +- See `/docs-components` Callout Spacing Rules + +--- + +## Content Principles + +### Intro Section +- **One sentence, ~15 words max** - State what the Hook does, not how it works +- βœ… "`useEffectEvent` is a React Hook that lets you separate events from Effects." +- ❌ "`useEffectEvent` is a React Hook that lets you extract non-reactive logic from your Effects into a reusable function called an Effect Event." + +### Reference Code Example +- Show just the API call (5-10 lines), not a full component +- Move full component examples to Usage section + +### Usage Section Structure +1. **First example: Core mental model** - Show the canonical use case with simplest concrete example +2. **Subsequent examples: Canonical use cases** - Name the *why* (e.g., "Avoid reconnecting to external systems"), show a concrete *how* + - Prefer broad canonical use cases over multiple narrow concrete examples + - The section title IS the teaching - "When would I use this?" should be answered by the heading + +### What to Include vs. Exclude +- **Never** document past bugs or fixed issues +- **Include** edge cases most developers will encounter +- **Exclude** niche edge cases (e.g., `this` binding, rare class patterns) + +### Caveats Section +- Include rules the linter enforces or that cause immediate errors +- Include fundamental usage restrictions +- Exclude implementation details unless they affect usage +- Exclude repetition of things explained elsewhere +- Keep each caveat to one sentence when possible + +### Troubleshooting Section +- Error headings only: "I'm getting an error: '[message]'" format +- Never document past bugs - if it's fixed, it doesn't belong here +- Focus on errors developers will actually encounter today + +### DeepDive Content +- **Goldilocks principle** - Deep enough for curious developers, short enough to not overwhelm +- Answer "why is it designed this way?" - not exhaustive technical details +- Readers who skip it should miss nothing essential for using the API +- If the explanation is getting long, you're probably explaining too much + +--- + +## Domain-Specific Guidance + +### Hooks + +**Returned function documentation:** +- Document setter/dispatch functions as separate `###` sections +- Use generic names: "set functions" not "setCount" +- Include stable identity caveat for returned functions + +**Dependency array documentation:** +- List what counts as reactive values +- Explain when dependencies are ignored +- Link to removing effect dependencies guide + +**Recipes usage:** +- Group related examples with meaningful titleText +- Each recipe has brief intro, Sandpack, and `` + +--- + +### Components + +**Props documentation:** +- Use `#### Props` instead of `#### Parameters` +- Mark optional props with `**optional**` prefix +- Use `` inline for canary-only props + +**JSX syntax in titles/headings:** +- Frontmatter title: `title: ` +- Reference heading: `` ### `` {/*suspense*/} `` + +--- + +### React-DOM + +**Common props linking:** +```md +`` supports all [common element props.](/reference/react-dom/components/common#common-props) +``` + +**Props categorization:** +- Controlled vs uncontrolled props grouped separately +- Form-specific props documented with action patterns +- MDN links for standard HTML attributes + +**Environment-specific notes:** +```mdx + + +This API is specific to Node.js. Environments with [Web Streams](MDN-link), like Deno and modern edge runtimes, should use [`renderToReadableStream`](/reference/react-dom/server/renderToReadableStream) instead. + + +``` + +**Progressive enhancement:** +- Document benefits for users without JavaScript +- Explain Server Function + form action integration +- Show hidden form field and `.bind()` patterns + +--- + +### RSC + +**RSC banner (before Intro):** +Always place `` component before `` for Server Component-only APIs. + +**Serialization type lists:** +When documenting Server Function arguments, list supported types: +```md +Supported types for Server Function arguments: + +* Primitives + * [string](MDN-link) + * [number](MDN-link) +* Iterables containing serializable values + * [Array](MDN-link) + * [Map](MDN-link) + +Notably, these are not supported: +* React elements, or [JSX](/learn/writing-markup-with-jsx) +* Functions (other than Server Functions) +``` + +**Bundle size comparisons:** +- Show "Not included in bundle" for server-only imports +- Annotate client bundle sizes with gzip: `// 35.9K (11.2K gzipped)` + +--- + +### Compiler + +**Configuration page structure:** +- Type (union type or interface) +- Default value +- Options/Valid values with descriptions + +**Directive documentation:** +- Placement requirements are critical +- Mode interaction tables showing combinations +- "Use sparingly" + "Plan for removal" patterns for escape hatches + +**Library author guides:** +- Audience-first intro +- Benefits/Why section +- Numbered step-by-step setup + +--- + +### ESLint + +**Rule Details section:** +- Explain "why" not just "what" +- Focus on React's underlying assumptions +- Describe consequences of violations + +**Invalid/Valid sections:** +- Standard intro: "Examples of [in]correct code for this rule:" +- Use X emoji for invalid, checkmark for valid +- Show inline comments explaining the violation + +**Configuration options:** +- Show shared settings (preferred) +- Show rule-level options (backward compatibility) +- Note precedence when both exist + +--- + +## Edge Cases + +For deprecated, canary, and version-specific component patterns (placement, syntax, examples), invoke `/docs-components`. + +**Quick placement rules:** +- `` after `` for page-level, after heading for method-level +- `` wrapper inline in Intro, `` in headings/props/caveats +- Version notes use `` with "Starting in React 19..." pattern + +**Removed APIs on index pages:** +```md +## Removed APIs {/*removed-apis*/} + +These APIs were removed in React 19: + +* [`render`](https://18.react.dev/reference/react-dom/render): use [`createRoot`](/reference/react-dom/client/createRoot) instead. +``` + +Link to previous version docs (18.react.dev) for removed API documentation. + +--- + +## Critical Rules + +1. **Heading IDs required:** `## Title {/*title-id*/}` (lowercase, hyphens) +2. **Sandpack main file needs `export default`** +3. **Active file syntax:** ` ```js src/File.js active ` +4. **Error headings in Troubleshooting:** Use `### I'm getting an error: "[message]" {/*id*/}` +5. **Section dividers (`---`)** required between headings (see Section Dividers below) +6. **InlineToc required:** Always include `` after Intro +7. **Consistent parameter format:** Use `* \`paramName\`: description` with `**optional**` prefix for optional params +8. **Numbered lists for array returns:** When hooks return arrays, use numbered lists in Returns section +9. **Generic names for returned functions:** Use "set functions" not "setCount" +10. **Props vs Parameters:** Use `#### Props` for Components (Type B), `#### Parameters` for Hooks/APIs (Type A) +11. **RSC placement:** `` component goes before ``, not after +12. **Canary markers:** Use `` wrapper inline in Intro, `` in headings/props +13. **Deprecated placement:** `` goes after `` for page-level, after heading for method-level +14. **Code comment emojis:** Use X for wrong, checkmark for correct in code examples +15. **No consecutive Pitfalls/Notes:** Combine into one component with titled subsections, or separate with prose/code (see `/docs-components`) + +For component heading level conventions (DeepDive, Pitfall, Note, Recipe headings), see `/docs-components`. + +### Section Dividers + +Use `---` horizontal rules to visually separate major sections: + +- **After ``** - Before `## Reference` heading +- **Between API subsections** - Between different function/hook definitions (e.g., between `useState()` and `set functions`) +- **Before `## Usage`** - Separates API reference from examples +- **Before `## Troubleshooting`** - Separates content from troubleshooting +- **Between EVERY Usage subsections** - When switching to a new major use case + +Always have a blank line before and after `---`. + +### Section ID Conventions + +| Section | ID Format | +|---------|-----------| +| Main function | `{/*functionname*/}` | +| Returned function | `{/*setstate*/}`, `{/*dispatch*/}` | +| Sub-section of returned function | `{/*setstate-parameters*/}` | +| Troubleshooting item | `{/*problem-description-slug*/}` | +| Pitfall | `{/*pitfall-description*/}` | +| Deep dive | `{/*deep-dive-topic*/}` | diff --git a/.claude/skills/react-expert/SKILL.md b/.claude/skills/react-expert/SKILL.md new file mode 100644 index 000000000..5ebcdee37 --- /dev/null +++ b/.claude/skills/react-expert/SKILL.md @@ -0,0 +1,335 @@ +--- +name: react-expert +description: Use when researching React APIs or concepts for documentation. Use when you need authoritative usage examples, caveats, warnings, or errors for a React feature. +--- + +# React Expert Research Skill + +## Overview + +This skill produces exhaustive documentation research on any React API or concept by searching authoritative sources (tests, source code, PRs, issues) rather than relying on LLM training knowledge. + + +**Skepticism Mandate:** You must be skeptical of your own knowledge. Claude is often trained on outdated or incorrect React patterns. Treat source material as the sole authority. If findings contradict your prior understanding, explicitly flag this discrepancy. + +**Red Flags - STOP if you catch yourself thinking:** +- "I know this API does X" β†’ Find source evidence first +- "Common pattern is Y" β†’ Verify in test files +- Generating example code β†’ Must have source file reference + + +## Invocation + +``` +/react-expert useTransition +/react-expert suspense boundaries +/react-expert startTransition +``` + +## Sources (Priority Order) + +1. **React Repo Tests** - Most authoritative for actual behavior +2. **React Source Code** - Warnings, errors, implementation details +3. **Git History** - Commit messages with context +4. **GitHub PRs & Comments** - Design rationale (via `gh` CLI) +5. **GitHub Issues** - Confusion/questions (facebook/react + reactjs/react.dev) +6. **React Working Group** - Design discussions for newer APIs +7. **Flow Types** - Source of truth for type signatures +8. **TypeScript Types** - Note discrepancies with Flow +9. **Current react.dev docs** - Baseline (not trusted as complete) + +**No web search** - No Stack Overflow, blog posts, or web searches. GitHub API via `gh` CLI is allowed. + +## Workflow + +### Step 1: Setup React Repo + +First, ensure the React repo is available locally: + +```bash +# Check if React repo exists, clone or update +if [ -d ".claude/react" ]; then + cd .claude/react && git pull origin main +else + git clone --depth=100 https://github.com/facebook/react.git .claude/react +fi +``` + +Get the current commit hash for the research document: +```bash +cd .claude/react && git rev-parse --short HEAD +``` + +### Step 2: Dispatch 6 Parallel Research Agents + +Spawn these agents IN PARALLEL using the Task tool. Each agent receives the skepticism preamble: + +> "You are researching React's ``. CRITICAL: Do NOT rely on your prior knowledge about this API. Your training may contain outdated or incorrect patterns. Only report what you find in the source files. If your findings contradict common understanding, explicitly highlight this discrepancy." + +| Agent | subagent_type | Focus | Instructions | +|-------|---------------|-------|--------------| +| test-explorer | Explore | Test files for usage patterns | Search `.claude/react/packages/*/src/__tests__/` for test files mentioning the topic. Extract actual usage examples WITH file paths and line numbers. | +| source-explorer | Explore | Warnings/errors in source | Search `.claude/react/packages/*/src/` for console.error, console.warn, and error messages mentioning the topic. Document trigger conditions. | +| git-historian | Explore | Commit messages | Run `git log --all --grep="" --oneline -50` in `.claude/react`. Read full commit messages for context. | +| pr-researcher | Explore | PRs introducing/modifying API | Run `gh pr list -R facebook/react --search "" --state all --limit 20`. Read key PR descriptions and comments. | +| issue-hunter | Explore | Issues showing confusion | Search issues in both `facebook/react` and `reactjs/react.dev` repos. Look for common questions and misunderstandings. | +| types-inspector | Explore | Flow + TypeScript signatures | Find Flow types in `.claude/react/packages/*/src/*.js` (look for `@flow` annotations). Find TS types in `.claude/react/packages/*/index.d.ts`. Note discrepancies. | + +### Step 3: Agent Prompts + +Use these exact prompts when spawning agents: + +#### test-explorer +``` +You are researching React's . + +CRITICAL: Do NOT rely on your prior knowledge about this API. Your training may contain outdated or incorrect patterns. Only report what you find in the source files. + +Your task: Find test files in .claude/react that demonstrate usage. + +1. Search for test files: Glob for `**/__tests__/**/**` and `**/__tests__/**/*.js` then grep for +2. For each relevant test file, extract: + - The test description (describe/it blocks) + - The actual usage code + - Any assertions about behavior + - Edge cases being tested +3. Report findings with exact file paths and line numbers + +Format your output as: +## Test File: +### Test: "" +```javascript + +``` +**Behavior:** +``` + +#### source-explorer +``` +You are researching React's . + +CRITICAL: Do NOT rely on your prior knowledge about this API. Only report what you find in the source files. + +Your task: Find warnings, errors, and implementation details for . + +1. Search .claude/react/packages/*/src/ for: + - console.error mentions of + - console.warn mentions of + - Error messages mentioning + - The main implementation file +2. For each warning/error, document: + - The exact message text + - The condition that triggers it + - The source file and line number + +Format your output as: +## Warnings & Errors +| Message | Trigger Condition | Source | +|---------|------------------|--------| +| "" | | | + +## Implementation Notes + +``` + +#### git-historian +``` +You are researching React's . + +CRITICAL: Do NOT rely on your prior knowledge. Only report what you find in git history. + +Your task: Find commit messages that explain design decisions. + +1. Run: cd .claude/react && git log --all --grep="" --oneline -50 +2. For significant commits, read full message: git show --stat +3. Look for: + - Initial introduction of the API + - Bug fixes (reveal edge cases) + - Behavior changes + - Deprecation notices + +Format your output as: +## Key Commits +### - +**Date:** +**Context:** +**Impact:** +``` + +#### pr-researcher +``` +You are researching React's . + +CRITICAL: Do NOT rely on your prior knowledge. Only report what you find in PRs. + +Your task: Find PRs that introduced or modified . + +1. Run: gh pr list -R facebook/react --search "" --state all --limit 20 --json number,title,url +2. For promising PRs, read details: gh pr view -R facebook/react +3. Look for: + - The original RFC/motivation + - Design discussions in comments + - Alternative approaches considered + - Breaking changes + +Format your output as: +## Key PRs +### PR #: +**URL:** <url> +**Summary:** <what it introduced/changed> +**Design Rationale:** <why this approach> +**Discussion Highlights:** <key points from comments> +``` + +#### issue-hunter +``` +You are researching React's <TOPIC>. + +CRITICAL: Do NOT rely on your prior knowledge. Only report what you find in issues. + +Your task: Find issues that reveal common confusion about <TOPIC>. + +1. Search facebook/react: gh issue list -R facebook/react --search "<topic>" --state all --limit 20 --json number,title,url +2. Search reactjs/react.dev: gh issue list -R reactjs/react.dev --search "<topic>" --state all --limit 20 --json number,title,url +3. For each issue, identify: + - What the user was confused about + - What the resolution was + - Any gotchas revealed + +Format your output as: +## Common Confusion +### Issue #<number>: <title> +**Repo:** <facebook/react or reactjs/react.dev> +**Confusion:** <what they misunderstood> +**Resolution:** <correct understanding> +**Gotcha:** <if applicable> +``` + +#### types-inspector +``` +You are researching React's <TOPIC>. + +CRITICAL: Do NOT rely on your prior knowledge. Only report what you find in type definitions. + +Your task: Find and compare Flow and TypeScript type signatures for <TOPIC>. + +1. Flow types (source of truth): Search .claude/react/packages/*/src/*.js for @flow annotations related to <topic> +2. TypeScript types: Search .claude/react/packages/*/index.d.ts and @types/react +3. Compare and note any discrepancies + +Format your output as: +## Flow Types (Source of Truth) +**File:** <path> +```flow +<exact type definition> +``` + +## TypeScript Types +**File:** <path> +```typescript +<exact type definition> +``` + +## Discrepancies +<any differences between Flow and TS definitions> +``` + +### Step 4: Synthesize Results + +After all agents complete, combine their findings into a single research document. + +**DO NOT add information from your own knowledge.** Only include what agents found in sources. + +### Step 5: Save Output + +Write the final document to `.claude/research/<topic>.md` + +Replace spaces in topic with hyphens (e.g., "suspense boundaries" β†’ "suspense-boundaries.md") + +## Output Document Template + +```markdown +# React Research: <topic> + +> Generated by /react-expert on YYYY-MM-DD +> Sources: React repo (commit <hash>), N PRs, M issues + +## Summary + +[Brief summary based SOLELY on source findings, not prior knowledge] + +## API Signature + +### Flow Types (Source of Truth) + +[From types-inspector agent] + +### TypeScript Types + +[From types-inspector agent] + +### Discrepancies + +[Any differences between Flow and TS] + +## Usage Examples + +### From Tests + +[From test-explorer agent - with file:line references] + +### From PRs/Issues + +[Real-world patterns from discussions] + +## Caveats & Gotchas + +[Each with source link] + +- **<gotcha>** - Source: <link> + +## Warnings & Errors + +| Message | Trigger Condition | Source File | +|---------|------------------|-------------| +[From source-explorer agent] + +## Common Confusion + +[From issue-hunter agent] + +## Design Decisions + +[From git-historian and pr-researcher agents] + +## Source Links + +### Commits +- <hash>: <description> + +### Pull Requests +- PR #<number>: <title> - <url> + +### Issues +- Issue #<number>: <title> - <url> +``` + +## Common Mistakes to Avoid + +1. **Trusting prior knowledge** - If you "know" something about the API, find the source evidence anyway +2. **Generating example code** - Every code example must come from an actual source file +3. **Skipping agents** - All 6 agents must run; each provides unique perspective +4. **Summarizing without sources** - Every claim needs a file:line or PR/issue reference +5. **Using web search** - No Stack Overflow, no blog posts, no social media + +## Verification Checklist + +Before finalizing the research document: + +- [ ] React repo is at `.claude/react` with known commit hash +- [ ] All 6 agents were spawned in parallel +- [ ] Every code example has a source file reference +- [ ] Warnings/errors table has source locations +- [ ] No claims made without source evidence +- [ ] Discrepancies between Flow/TS types documented +- [ ] Source links section is complete diff --git a/.claude/skills/review-docs/SKILL.md b/.claude/skills/review-docs/SKILL.md new file mode 100644 index 000000000..61a6a0e05 --- /dev/null +++ b/.claude/skills/review-docs/SKILL.md @@ -0,0 +1,20 @@ +--- +name: review-docs +description: Use when reviewing React documentation for structure, components, and style compliance +--- +CRITICAL: do not load these skills yourself. + +Run these tasks in parallel for the given file(s). Each agent checks different aspectsβ€”not all apply to every file: + +- [ ] Ask docs-reviewer agent to review {files} with docs-writer-learn (only for files in src/content/learn/). +- [ ] Ask docs-reviewer agent to review {files} with docs-writer-reference (only for files in src/content/reference/). +- [ ] Ask docs-reviewer agent to review {files} with docs-writer-blog (only for files in src/content/blog/). +- [ ] Ask docs-reviewer agent to review {files} with docs-voice (all documentation files). +- [ ] Ask docs-reviewer agent to review {files} with docs-components (all documentation files). +- [ ] Ask docs-reviewer agent to review {files} with docs-sandpack (files containing Sandpack examples). + +If no file is specified, check git status for modified MDX files in `src/content/`. + +The docs-reviewer will return a checklist of the issues it found. Respond with the full checklist and line numbers from all agents, and prompt the user to create a plan to fix these issues. + + diff --git a/.claude/skills/write/SKILL.md b/.claude/skills/write/SKILL.md new file mode 100644 index 000000000..3099b3a0c --- /dev/null +++ b/.claude/skills/write/SKILL.md @@ -0,0 +1,176 @@ +--- +name: write +description: Use when creating new React documentation pages or updating existing ones. Accepts instructions like "add optimisticKey reference docs", "update ViewTransition with Activity", or "transition learn docs". +--- + +# Documentation Writer + +Orchestrates research, writing, and review for React documentation. + +## Invocation + +``` +/write add optimisticKey β†’ creates new reference docs +/write update ViewTransition Activity β†’ updates ViewTransition docs to cover Activity +/write transition learn docs β†’ creates new learn docs for transitions +/write blog post for React 20 β†’ creates a new blog post +``` + +## Workflow + +```dot +digraph write_flow { + rankdir=TB; + "Parse intent" [shape=box]; + "Research (parallel)" [shape=box]; + "Synthesize plan" [shape=box]; + "Write docs" [shape=box]; + "Review docs" [shape=box]; + "Issues found?" [shape=diamond]; + "Done" [shape=doublecircle]; + + "Parse intent" -> "Research (parallel)"; + "Research (parallel)" -> "Synthesize plan"; + "Synthesize plan" -> "Write docs"; + "Write docs" -> "Review docs"; + "Review docs" -> "Issues found?"; + "Issues found?" -> "Write docs" [label="yes - fix"]; + "Issues found?" -> "Done" [label="no"]; +} +``` + +### Step 1: Parse Intent + +Determine from the user's instruction: + +| Field | How to determine | +|-------|------------------| +| **Action** | "add"/"create"/"new" = new page; "update"/"edit"/"with" = modify existing | +| **Topic** | The React API or concept (e.g., `optimisticKey`, `ViewTransition`, `transitions`) | +| **Doc type** | "reference" (default for APIs/hooks/components), "learn" (for concepts/guides), "blog" (for announcements) | +| **Target file** | For updates: find existing file in `src/content/`. For new: determine path from doc type | + +If the intent is ambiguous, ask the user to clarify before proceeding. + +### Step 2: Research (Parallel Agents) + +Spawn these agents **in parallel**: + +#### Agent 1: React Expert Research + +Use a Task agent (subagent_type: `general-purpose`) to invoke `/react-expert <topic>`. This researches the React source code, tests, PRs, issues, and type signatures. + +**Prompt:** +``` +Invoke the /react-expert skill for <TOPIC>. Follow the skill's full workflow: +setup the React repo, dispatch all 6 research agents in parallel, synthesize +results, and save to .claude/research/<topic>.md. Return the full research document. +``` + +#### Agent 2: Existing Docs Audit + +Use a Task agent (subagent_type: `Explore`) to find and read existing documentation for the topic. + +**Prompt:** +``` +Find all existing documentation related to <TOPIC> in this repo: +1. Search src/content/ for files mentioning <TOPIC> +2. Read any matching files fully +3. For updates: identify what sections exist and what's missing +4. For new pages: identify related pages to understand linking/cross-references +5. Check src/sidebarLearn.json and src/sidebarReference.json for navigation placement + +Return: list of existing files with summaries, navigation structure, and gaps. +``` + +#### Agent 3: Use Case Research + +Use a Task agent (subagent_type: `general-purpose`) with web search to find common use cases and patterns. + +**Prompt:** +``` +Search the web for common use cases and patterns for React's <TOPIC>. +Focus on: +1. Real-world usage patterns developers actually need +2. Common mistakes or confusion points +3. Migration patterns (if replacing an older API) +4. Framework integration patterns (Next.js, Remix, etc.) + +Return a summary of the top 5-8 use cases with brief code sketches. +Do NOT search Stack Overflow. Focus on official docs, GitHub discussions, +and high-quality technical blogs. +``` + +### Step 3: Synthesize Writing Plan + +After all research agents complete, create a writing plan that includes: + +1. **Page type** (from docs-writer-reference decision tree or learn/blog type) +2. **File path** for the new or updated file +3. **Outline** with section headings matching the appropriate template +4. **Content notes** for each section, drawn from research: + - API signature and parameters (from react-expert types) + - Usage examples (from react-expert tests + use case research) + - Caveats and pitfalls (from react-expert warnings/errors/issues) + - Cross-references to related pages (from docs audit) +5. **Navigation changes** needed (sidebar JSON updates) + +Present this plan to the user and confirm before proceeding. + +### Step 4: Write Documentation + +Dispatch a Task agent (subagent_type: `general-purpose`) to write the documentation. + +**The agent prompt MUST include:** + +1. The full writing plan from Step 3 +2. An instruction to invoke the appropriate skill: + - `/docs-writer-reference` for reference pages + - `/docs-writer-learn` for learn pages + - `/docs-writer-blog` for blog posts +3. An instruction to invoke `/docs-components` for MDX component patterns +4. An instruction to invoke `/docs-sandpack` if adding interactive code examples +5. The research document content (key findings, not the full dump) + +**Prompt template:** +``` +You are writing React documentation. Follow these steps: + +1. Invoke /docs-writer-<TYPE> to load the page template and conventions +2. Invoke /docs-components to load MDX component patterns +3. Invoke /docs-sandpack if you need interactive code examples +4. Write the documentation following the plan below + +PLAN: +<writing plan from Step 3> + +RESEARCH FINDINGS: +<key findings from Step 2 agents> + +Write the file to: <target file path> +Also update <sidebar JSON> if adding a new page. +``` + +### Step 5: Review Documentation + +Invoke `/review-docs` on the written files. This dispatches parallel review agents checking: +- Structure compliance (docs-writer-*) +- Voice and style (docs-voice) +- Component usage (docs-components) +- Sandpack patterns (docs-sandpack) + +### Step 6: Fix Issues + +If the review finds issues: +1. Present the review checklist to the user +2. Fix the issues identified +3. Re-run `/review-docs` on the fixed files +4. Repeat until clean + +## Important Rules + +- **Always research before writing.** Never write docs from LLM knowledge alone. +- **Always confirm the plan** with the user before writing. +- **Always review** with `/review-docs` after writing. +- **Match existing patterns.** Read neighboring docs to match style and depth. +- **Update navigation.** New pages need sidebar entries. diff --git a/.claude/skills/write/diagrams/write_flow.svg b/.claude/skills/write/diagrams/write_flow.svg new file mode 100644 index 000000000..49056ef11 --- /dev/null +++ b/.claude/skills/write/diagrams/write_flow.svg @@ -0,0 +1,100 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" + "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"> +<!-- Generated by graphviz version 14.1.2 (20260124.0452) + --> +<!-- Title: write_flow Pages: 1 --> +<svg width="182pt" height="531pt" + viewBox="0.00 0.00 182.00 531.00" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"> +<g id="graph0" class="graph" transform="scale(1 1) rotate(0) translate(4 527.26)"> +<title>write_flow + + + +Parse intent + +Parse intent + + + +Research (parallel) + +Research (parallel) + + + +Parse intent->Research (parallel) + + + + + +Synthesize plan + +Synthesize plan + + + +Research (parallel)->Synthesize plan + + + + + +Write docs + +Write docs + + + +Synthesize plan->Write docs + + + + + +Review docs + +Review docs + + + +Write docs->Review docs + + + + + +Issues found? + +Issues found? + + + +Review docs->Issues found? + + + + + +Issues found?->Write docs + + +yes - fix + + + +Done + + +Done + + + +Issues found?->Done + + +no + + + diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 000000000..1bb2661fd --- /dev/null +++ b/.editorconfig @@ -0,0 +1,7 @@ +root = true + +[*] +charset = utf-8 +end_of_line = lf +insert_final_newline = true +indent_style = space diff --git a/.env.development b/.env.development new file mode 100644 index 000000000..e69de29bb diff --git a/.env.production b/.env.production new file mode 100644 index 000000000..8d10ee6a1 --- /dev/null +++ b/.env.production @@ -0,0 +1 @@ +NEXT_PUBLIC_GA_TRACKING_ID = 'G-C4MKP7MN1V' diff --git a/.eslintignore b/.eslintignore index ee6604687..d15200cf2 100644 --- a/.eslintignore +++ b/.eslintignore @@ -1,13 +1,5 @@ -node_modules/* - -# Skip beta -beta/* - -# Ignore markdown files and examples -content/* - -# Ignore built files -public/* - -# Ignore examples -examples/* \ No newline at end of file +scripts +plugins +next.config.js +.claude/ +worker-bundle.dist.js diff --git a/.eslintrc b/.eslintrc index a51454ef2..935fa2f23 100644 --- a/.eslintrc +++ b/.eslintrc @@ -1,18 +1,38 @@ { - "extends": [ - "fbjs" - ], - "plugins": [ - "prettier", - "react" - ], - "parser": "babel-eslint", + "root": true, + "extends": "next/core-web-vitals", + "parser": "@typescript-eslint/parser", + "plugins": ["@typescript-eslint", "eslint-plugin-react-compiler", "local-rules"], "rules": { - "relay/graphql-naming": 0, - "max-len": 0 + "no-unused-vars": "off", + "@typescript-eslint/no-unused-vars": ["error", {"varsIgnorePattern": "^_"}], + "react-hooks/exhaustive-deps": "error", + "react/no-unknown-property": ["error", {"ignore": ["meta"]}], + "react-compiler/react-compiler": "error", + "local-rules/lint-markdown-code-blocks": "error", + "no-trailing-spaces": "error" }, "env": { "node": true, - "browser": true - } + "commonjs": true, + "browser": true, + "es6": true + }, + "overrides": [ + { + "files": ["src/content/**/*.md"], + "parser": "./eslint-local-rules/parser", + "parserOptions": { + "sourceType": "module" + }, + "rules": { + "no-unused-vars": "off", + "@typescript-eslint/no-unused-vars": "off", + "react-hooks/exhaustive-deps": "off", + "react/no-unknown-property": "off", + "react-compiler/react-compiler": "off", + "local-rules/lint-markdown-code-blocks": "error" + } + } + ] } diff --git a/.flowconfig b/.flowconfig deleted file mode 100644 index baf4b0255..000000000 --- a/.flowconfig +++ /dev/null @@ -1,36 +0,0 @@ -[ignore] - -/beta/.* -/content/.* -/node_modules/.* -/public/.* - -[include] - -[libs] -./node_modules/fbjs/flow/lib/dev.js -./flow - -[options] -module.system=haste -module.system.node.resolve_dirname=node_modules -module.system.node.resolve_dirname=src - -esproposal.class_static_fields=enable -esproposal.class_instance_fields=enable -unsafe.enable_getters_and_setters=true - -munge_underscores=false - -suppress_type=$FlowIssue -suppress_type=$FlowFixMe -suppress_type=$FixMe -suppress_type=$FlowExpectedError - -suppress_comment=\\(.\\|\n\\)*\\$FlowFixMe\\($\\|[^(]\\|(\\(>=0\\.\\(3[0-3]\\|[1-2][0-9]\\|[0-9]\\).[0-9]\\)? *\\(site=[a-z,_]*www[a-z,_]*\\)?)\\) -suppress_comment=\\(.\\|\n\\)*\\$FlowIssue\\((\\(>=0\\.\\(3[0-3]\\|[1-2][0-9]\\|[0-9]\\).[0-9]\\)? *\\(site=[a-z,_]*www[a-z,_]*\\)?)\\)?:? #[0-9]+ -suppress_comment=\\(.\\|\n\\)*\\$FlowFixedInNextDeploy -suppress_comment=\\(.\\|\n\\)*\\$FlowExpectedError - -[version] -^0.56.0 diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 000000000..8a5a53391 --- /dev/null +++ b/.gitattributes @@ -0,0 +1,4 @@ +# https://git-scm.com/docs/gitattributes + +# Ensure consistent EOL(LF) for all files that Git considers text files. +* text=auto eol=lf diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS new file mode 100644 index 000000000..b7e5c36c1 --- /dev/null +++ b/.github/CODEOWNERS @@ -0,0 +1 @@ +* @hg-pyun @gnujoow @eomttt @lumirlumir diff --git a/.github/ISSUE_TEMPLATE/0-bug.yml b/.github/ISSUE_TEMPLATE/0-bug.yml new file mode 100644 index 000000000..56d2e8540 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/0-bug.yml @@ -0,0 +1,34 @@ +name: "πŸ› Report a bug" +description: "Report a problem on the website." +title: "[Bug]: " +labels: ["bug: unconfirmed"] +body: + - type: textarea + attributes: + label: Summary + description: | + A clear and concise summary of what the bug is. + placeholder: | + Example bug report: + When I click the "Submit" button on "Feedback", nothing happens. + validations: + required: true + - type: input + attributes: + label: Page + description: | + What page(s) did you encounter this bug on? + placeholder: | + https://react.dev/ + validations: + required: true + - type: textarea + attributes: + label: Details + description: | + Please provide any additional details about the bug. + placeholder: | + Example details: + The "Submit" button is unresponsive. I've tried refreshing the page and using a different browser, but the issue persists. + validations: + required: false diff --git a/.github/ISSUE_TEMPLATE/1-typo.yml b/.github/ISSUE_TEMPLATE/1-typo.yml new file mode 100644 index 000000000..c86557a11 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/1-typo.yml @@ -0,0 +1,34 @@ +name: "🀦 Typo or mistake" +description: "Report a typo or mistake in the docs." +title: "[Typo]: " +labels: ["type: typos"] +body: + - type: textarea + attributes: + label: Summary + description: | + A clear and concise summary of what the mistake is. + placeholder: | + Example: + The code example on the "useReducer" page includes an unused variable `nextId`. + validations: + required: true + - type: input + attributes: + label: Page + description: | + What page is the typo on? + placeholder: | + https://react.dev/ + validations: + required: true + - type: textarea + attributes: + label: Details + description: | + Please provide a explanation for why this is a mistake. + placeholder: | + Example mistake: + In the "useReducer" section of the "API Reference" page, the code example under "Writing a reducer function" includes an unused variable `nextId` that should be removed. + validations: + required: false diff --git a/.github/ISSUE_TEMPLATE/3-framework.yml b/.github/ISSUE_TEMPLATE/3-framework.yml new file mode 100644 index 000000000..87f03a660 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/3-framework.yml @@ -0,0 +1,116 @@ +name: "πŸ“„ Suggest new framework" +description: "I am a framework author applying to be included as a recommended framework." +title: "[Framework]: " +labels: ["type: framework"] +body: + - type: markdown + attributes: + value: | + ## Apply to be included as a recommended React framework + + _This form is for framework authors to apply to be included as a recommended [React framework](https://react.dev/learn/creating-a-react-app). If you are not a framework author, please contact the authors before submitting._ + + Our goal when recommending a framework is to start developers with a React project that solves common problems like code splitting, data fetching, routing, and HTML generation without any extra work later. We believe this will allow users to get started quickly with React, and scale their app to production. + + While we understand that many frameworks may want to be featured, this page is not a place to advertise every possible React framework or all frameworks that you can add React to. There are many great frameworks that offer support for React that are not listed in our guides. The frameworks we recommend have invested significantly in the React ecosystem, and collaborated with the React team to be compatible with our [full-stack React architecture vision](https://react.dev/learn/creating-a-react-app#which-features-make-up-the-react-teams-full-stack-architecture-vision). + + To be included, frameworks must meet the following criteria: + + - **Free & open-source**: must be open source and free to use. + - **Well maintained**. must be actively maintained, providing bug fixes and improvements. + - **Active community**: must have a sufficiently large and active community to support users. + - **Clear onboarding**: must have clear install steps to install the React version of the framework. + - **Ecosystem compatibility**: must support using the full range of libraries and tools in the React ecosystem. + - **Self-hosting option**: must support an option to self-host applications without losing access to features. + - **Developer experience**. must allow developers to be productive by supporting features like Fast Refresh. + - **User experience**. must provide built-in support for common problems like routing and data-fetching. + - **Compatible with our future vision for React**. React evolves over time, and frameworks that do not align with React’s direction risk isolating their users from the main React ecosystem over time. To be included on this page we must feel confident that the framework is setting its users up for success with React over time. + + Please note, we have reviewed most of the popular frameworks available today, so it is unlikely we have not considered your framework already. But if you think we missed something, please complete the application below. + - type: input + attributes: + label: Name + description: | + What is the name of your framework? + validations: + required: true + - type: input + attributes: + label: Homepage + description: | + What is the URL of your homepage? + validations: + required: true + - type: input + attributes: + label: Install instructions + description: | + What is the URL of your getting started guide? + validations: + required: true + - type: dropdown + attributes: + label: Is your framework open source? + description: | + We only recommend free and open source frameworks. + options: + - 'No' + - 'Yes' + validations: + required: true + - type: textarea + attributes: + label: Well maintained + description: | + Please describe how your framework is actively maintained. Include recent releases, bug fixes, and improvements as examples. + validations: + required: true + - type: textarea + attributes: + label: Active community + description: | + Please describe your community. Include the size of your community, and links to community resources. + validations: + required: true + - type: textarea + attributes: + label: Clear onboarding + description: | + Please describe how a user can install your framework with React. Include links to any relevant documentation. + validations: + required: true + - type: textarea + attributes: + label: Ecosystem compatibility + description: | + Please describe any limitations your framework has with the React ecosystem. Include any libraries or tools that are not compatible with your framework. + validations: + required: true + - type: textarea + attributes: + label: Self-hosting option + description: | + Please describe how your framework supports self-hosting. Include any limitations to features when self-hosting. Also include whether you require a server to deploy your framework. + validations: + required: true + - type: textarea + attributes: + label: Developer Experience + description: | + Please describe how your framework provides a great developer experience. Include any limitations to React features like React DevTools, Chrome DevTools, and Fast Refresh. + validations: + required: true + - type: textarea + attributes: + label: User Experience + description: | + Please describe how your framework helps developers create high quality user experiences by solving common use-cases. Include specifics for how your framework offers built-in support for code-splitting, routing, HTML generation, and data-fetching in a way that avoids client/server waterfalls by default. Include details on how you offer features such as SSG and SSR. + validations: + required: true + - type: textarea + attributes: + label: Compatible with our future vision for React + description: | + Please describe how your framework aligns with our future vision for React. Include how your framework will evolve with React over time, and your plans to support future React features like React Server Components. + validations: + required: true diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml new file mode 100644 index 000000000..63e310e0b --- /dev/null +++ b/.github/ISSUE_TEMPLATE/config.yml @@ -0,0 +1,7 @@ +contact_links: + - name: πŸ“ƒ Bugs in React + url: https://github.com/facebook/react/issues/new/choose + about: This issue tracker is not for bugs in React. Please file React issues here. + - name: πŸ€” Questions and Help + url: https://reactjs.org/community/support.html + about: This issue tracker is not for support questions. Please refer to the React community's help and discussion forums. diff --git a/.github/ISSUE_TEMPLATE/need-translation.md b/.github/ISSUE_TEMPLATE/need-translation.md new file mode 100644 index 000000000..ea0adf842 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/need-translation.md @@ -0,0 +1,20 @@ +--- +name: λ²ˆμ—­ ν•„μš” +about: λ²ˆμ—­μ΄ ν•„μš”ν•œ λ¬Έμ„œμ— λŒ€ν•΄ 이 ν…œν”Œλ¦Ώμ„ μ‚¬μš©ν•΄μ£Όμ„Έμš” +title: '[λ²ˆμ—­ ν•„μš”]: ' +labels: 'need translation' +assignees: '' +--- + +## Summary + + + +## Page + + + + +## Details + + diff --git a/.github/ISSUE_TEMPLATE/term.md b/.github/ISSUE_TEMPLATE/term.md new file mode 100644 index 000000000..7064fa165 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/term.md @@ -0,0 +1,21 @@ +--- +name: Term +about: λ¬Έμ„œμ—μ„œ μ‚¬μš©λ˜λŠ” μš©μ–΄ λ²ˆμ—­μ— λ…Όμ˜κ°€ ν•„μš”ν•œ 경우 이 ν…œν”Œλ¦Ώμ„ μ‚¬μš©ν•΄μ£Όμ„Έμš” +title: '' +labels: discussion, term +assignees: '' +--- + +## λ…Όμ˜ν•˜κ³ μž ν•˜λŠ” μš©μ–΄ + +## ν•΄λ‹Ή μš©μ–΄κ°€ λ“±μž₯ν•˜λŠ” μ›λ¬Έμ˜ λ¬Έμž₯ + +--- + +## λ…Όμ˜κ°€ μ™„λ£Œλœ ν›„ + +1. μ•„λž˜ μ½”λ“œλ₯Ό μ—…λ°μ΄νŠΈ ν•΄μ£Όμ„Έμš”. + - [ ] [`/textlint/data/rules/translateGlossary.js`](https://github.com/reactjs/ko.react.dev/blob/main/textlint/data/rules/translateGlossary.js) + +2. μš©μ–΄ 사전에 μ—…λ°μ΄νŠΈλœ 내역이 정상 λ°˜μ˜λ˜μ—ˆλ‚˜ ν™•μΈν•΄μ£Όμ„Έμš”. (ν•΄λ‹Ή 내역은 husky의 pre-commit 훅을 톡해 μžλ™ μ—…λ°μ΄νŠΈ λ©λ‹ˆλ‹€.) + - [ ] [`/wiki/translate-glossary.md`](https://github.com/reactjs/ko.react.dev/blob/main/wiki/translate-glossary.md) diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index 1b2af6aeb..5bbfcb602 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -1,20 +1,26 @@ -Please see the Contribution Guide for guidelines: +# -https://github.com/reactjs/reactjs.org/blob/main/CONTRIBUTING.md + -If your PR references an existing issue, please add the issue number below +## ν•„μˆ˜ 확인 사항 ---> +- [ ] [κΈ°μ—¬μž 행동 κ°•λ Ή κ·œμ•½Code of Conduct](https://github.com/reactjs/ko.react.dev/blob/main/CODE_OF_CONDUCT.md) +- [ ] [κΈ°μ—¬ κ°€μ΄λ“œλΌμΈContributing](https://github.com/reactjs/ko.react.dev/blob/main/CONTRIBUTING.md) +- [ ] [곡톡 μŠ€νƒ€μΌ κ°€μ΄λ“œUniversal Style Guide](https://github.com/reactjs/ko.react.dev/blob/main/wiki/universal-style-guide.md) +- [ ] [λ²ˆμ—­μ„ μœ„ν•œ λͺ¨λ²” 사둀Best Practices for Translation](https://github.com/reactjs/ko.react.dev/blob/main/wiki/best-practices-for-translation.md) +- [ ] [λ²ˆμ—­ μš©μ–΄ 정리Translate Glossary](https://github.com/reactjs/ko.react.dev/blob/main/wiki/translate-glossary.md) +- [ ] [`textlint` κ°€μ΄λ“œTextlint Guide](https://github.com/reactjs/ko.react.dev/blob/main/wiki/textlint-guide.md) +- [ ] [λ§žμΆ€λ²• 검사Spelling Check](https://nara-speller.co.kr/speller/) -## Progress +## 선택 확인 사항 -- [ ] λ²ˆμ—­ μ΄ˆμ•ˆ μž‘μ„± (Draft translation) -- [ ] [곡톡 μŠ€νƒ€μΌ κ°€μ΄λ“œ 확인 (Check the common style guide)](https://github.com/reactjs/ko.reactjs.org/blob/master/UNIVERSAL-STYLE-GUIDE.md) -- [ ] [λͺ¨λ²”사둀 확인 (Check best practices)](https://github.com/reactjs/ko.reactjs.org/wiki/Best-practices-for-translation) -- [ ] [μš©μ–΄ 확인 (Check the term)](https://github.com/reactjs/ko.reactjs.org/wiki/Translate-Glossary) -- [ ] [λ§žμΆ€λ²• 검사 (Spelling check)](http://speller.cs.pusan.ac.kr/) -- [ ] 리뷰 반영 (Resolve reviews) +- [ ] λ²ˆμ—­ μ΄ˆμ•ˆ μž‘μ„±Draft Translation +- [ ] 리뷰 반영Resolve Reviews diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 000000000..97f2a39ea --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,8 @@ +version: 2 +updates: + - package-ecosystem: "npm" + directory: "/" + schedule: + interval: "weekly" + # Disable Dependabot. Doing it here so it propagates to translation forks. + open-pull-requests-limit: 0 diff --git a/.github/labeler.yml b/.github/labeler.yml deleted file mode 100644 index 7768da2ba..000000000 --- a/.github/labeler.yml +++ /dev/null @@ -1,2 +0,0 @@ -beta: -- beta/**/* diff --git a/.github/workflows/analyze.yml b/.github/workflows/analyze.yml index b82891165..83e7f2e8a 100644 --- a/.github/workflows/analyze.yml +++ b/.github/workflows/analyze.yml @@ -7,57 +7,63 @@ on: - main # change this if your default branch is named differently workflow_dispatch: +permissions: {} + jobs: analyze: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v4 - name: Set up node - uses: actions/setup-node@v1 + uses: actions/setup-node@v4 with: - node-version: "14.x" + node-version: '20.x' + cache: yarn + cache-dependency-path: yarn.lock - - name: Install dependencies - uses: bahmutov/npm-install@v1.6.0 + - name: Restore cached node_modules + uses: actions/cache@v4 with: - working-directory: 'beta' + path: '**/node_modules' + key: node_modules-${{ runner.arch }}-${{ runner.os }}-${{ hashFiles('yarn.lock') }} + + - name: Install deps + run: yarn install --frozen-lockfile - name: Restore next build - uses: actions/cache@v2 + uses: actions/cache@v4 id: restore-build-cache env: cache-name: cache-next-build with: - path: beta/.next/cache + path: .next/cache # change this if you prefer a more strict cache key: ${{ runner.os }}-build-${{ env.cache-name }} - name: Build next.js app # change this if your site requires a custom build command run: ./node_modules/.bin/next build - working-directory: beta # Here's the first place where next-bundle-analysis' own script is used # This step pulls the raw bundle stats for the current bundle - name: Analyze bundle - run: npx -p nextjs-bundle-analysis report - working-directory: beta + run: npx -p nextjs-bundle-analysis@0.5.0 report - name: Upload bundle - uses: actions/upload-artifact@v2 + uses: actions/upload-artifact@v4 with: - path: beta/.next/analyze/__bundle_analysis.json + path: .next/analyze/__bundle_analysis.json name: bundle_analysis.json - name: Download base branch bundle stats - uses: dawidd6/action-download-artifact@v2 + uses: dawidd6/action-download-artifact@268677152d06ba59fcec7a7f0b5d961b6ccd7e1e if: success() && github.event.number with: workflow: analyze.yml branch: ${{ github.event.pull_request.base.ref }} name: bundle_analysis.json - path: beta/.next/analyze/base/bundle + path: .next/analyze/base/bundle # And here's the second place - this runs after we have both the current and # base branch bundle stats, and will compare them to determine what changed. @@ -75,19 +81,18 @@ jobs: - name: Compare with base branch bundle if: success() && github.event.number run: ls -laR .next/analyze/base && npx -p nextjs-bundle-analysis compare - working-directory: beta - name: Upload analysis comment - uses: actions/upload-artifact@v2 + uses: actions/upload-artifact@v4 with: name: analysis_comment.txt - path: beta/.next/analyze/__bundle_analysis_comment.txt + path: .next/analyze/__bundle_analysis_comment.txt - name: Save PR number run: echo ${{ github.event.number }} > ./pr_number - name: Upload PR number - uses: actions/upload-artifact@v2 + uses: actions/upload-artifact@v4 with: name: pr_number path: ./pr_number diff --git a/.github/workflows/analyze_comment.yml b/.github/workflows/analyze_comment.yml index 8166089fd..fcac37738 100644 --- a/.github/workflows/analyze_comment.yml +++ b/.github/workflows/analyze_comment.yml @@ -2,10 +2,15 @@ name: Analyze Bundle (Comment) on: workflow_run: - workflows: ["Analyze Bundle"] + workflows: ['Analyze Bundle'] types: - completed +permissions: + contents: read + issues: write + pull-requests: write + jobs: comment: runs-on: ubuntu-latest @@ -14,7 +19,7 @@ jobs: github.event.workflow_run.conclusion == 'success' }} steps: - name: Download base branch bundle stats - uses: dawidd6/action-download-artifact@v2 + uses: dawidd6/action-download-artifact@268677152d06ba59fcec7a7f0b5d961b6ccd7e1e with: workflow: analyze.yml run_id: ${{ github.event.workflow_run.id }} @@ -22,7 +27,7 @@ jobs: path: analysis_comment.txt - name: Download PR number - uses: dawidd6/action-download-artifact@v2 + uses: dawidd6/action-download-artifact@268677152d06ba59fcec7a7f0b5d961b6ccd7e1e with: workflow: analyze.yml run_id: ${{ github.event.workflow_run.id }} @@ -33,40 +38,23 @@ jobs: id: get-comment-body if: success() run: | + echo 'body<> $GITHUB_OUTPUT + echo '' >> $GITHUB_OUTPUT + echo '## Size changes' >> $GITHUB_OUTPUT + echo '' >> $GITHUB_OUTPUT + echo '
    ' >> $GITHUB_OUTPUT + echo '' >> $GITHUB_OUTPUT + cat analysis_comment.txt/__bundle_analysis_comment.txt >> $GITHUB_OUTPUT + echo '' >> $GITHUB_OUTPUT + echo '
    ' >> $GITHUB_OUTPUT + echo '' >> $GITHUB_OUTPUT + echo 'EOF' >> $GITHUB_OUTPUT pr_number=$(cat pr_number/pr_number) - body=$(cat analysis_comment.txt/__bundle_analysis_comment.txt) - body="## Size Changes -
    + echo "pr-number=$pr_number" >> $GITHUB_OUTPUT - ${body} - -
    " - body="${body//'%'/'%25'}" - body="${body//$'\n'/'%0A'}" - body="${body//$'\r'/'%0D'}" - echo ::set-output name=body::$body - echo ::set-output name=pr-number::$pr_number - - - name: Find Comment - uses: peter-evans/find-comment@v1 - if: success() - id: fc - with: - issue-number: ${{ steps.get-comment-body.outputs.pr-number }} - body-includes: "" - - - name: Create Comment - uses: peter-evans/create-or-update-comment@v1.4.4 - if: success() && steps.fc.outputs.comment-id == 0 - with: - issue-number: ${{ steps.get-comment-body.outputs.pr-number }} - body: ${{ steps.get-comment-body.outputs.body }} - - - name: Update Comment - uses: peter-evans/create-or-update-comment@v1.4.4 - if: success() && steps.fc.outputs.comment-id != 0 + - name: Comment + uses: marocchino/sticky-pull-request-comment@52423e01640425a022ef5fd42c6fb5f633a02728 with: - issue-number: ${{ steps.get-comment-body.outputs.pr-number }} - body: ${{ steps.get-comment-body.outputs.body }} - comment-id: ${{ steps.fc.outputs.comment-id }} - edit-mode: replace \ No newline at end of file + header: next-bundle-analysis + number: ${{ steps.get-comment-body.outputs.pr-number }} + message: ${{ steps.get-comment-body.outputs.body }} diff --git a/.github/workflows/beta_site_lint.yml b/.github/workflows/beta_site_lint.yml deleted file mode 100644 index 28b9d8da8..000000000 --- a/.github/workflows/beta_site_lint.yml +++ /dev/null @@ -1,30 +0,0 @@ -name: Beta Site Lint / Heading ID check - -on: - push: - branches: - - main # change this if your default branch is named differently - pull_request: - types: [opened, synchronize, reopened] - -jobs: - lint: - runs-on: ubuntu-latest - - name: Lint on node 12.x and ubuntu-latest - - steps: - - uses: actions/checkout@v1 - - name: Use Node.js 12.x - uses: actions/setup-node@v1 - with: - node-version: 12.x - - - name: Install deps and build (with cache) - uses: bahmutov/npm-install@v1.6.0 - with: - working-directory: 'beta' - - - - name: Lint codebase - run: cd beta && yarn ci-check diff --git a/.github/workflows/label.yml b/.github/workflows/label.yml deleted file mode 100644 index 90a961d4c..000000000 --- a/.github/workflows/label.yml +++ /dev/null @@ -1,22 +0,0 @@ -# This workflow will triage pull requests and apply a label based on the -# paths that are modified in the pull request. -# -# To use this workflow, you will need to set up a .github/labeler.yml -# file with configuration. For more information, see: -# https://github.com/actions/labeler - -name: Labeler -on: [pull_request_target] - -jobs: - label: - - runs-on: ubuntu-latest - permissions: - contents: read - pull-requests: write - - steps: - - uses: actions/labeler@v2 - with: - repo-token: "${{ secrets.GITHUB_TOKEN }}" diff --git a/.github/workflows/nodejs.yml b/.github/workflows/nodejs.yml deleted file mode 100644 index a74102e24..000000000 --- a/.github/workflows/nodejs.yml +++ /dev/null @@ -1,27 +0,0 @@ -name: Lint / Flow check - -on: - push: - branches: - - main # change this if your default branch is named differently - pull_request: - types: [opened, synchronize, reopened] - -jobs: - lint: - runs-on: ubuntu-latest - - name: Lint on node 12.x and ubuntu-latest - - steps: - - uses: actions/checkout@v1 - - name: Use Node.js 12.x - uses: actions/setup-node@v1 - with: - node-version: 12.x - - - name: Install deps and build (with cache) - uses: bahmutov/npm-install@v1.6.0 - - - name: Lint codebase - run: yarn ci-check diff --git a/.github/workflows/site_lint.yml b/.github/workflows/site_lint.yml new file mode 100644 index 000000000..81a04601c --- /dev/null +++ b/.github/workflows/site_lint.yml @@ -0,0 +1,37 @@ +name: Site Lint / Heading ID check + +on: + push: + branches: + - main # change this if your default branch is named differently + pull_request: + types: [opened, synchronize, reopened] + +permissions: {} + +jobs: + lint: + runs-on: ubuntu-latest + + name: Lint on node 20.x and ubuntu-latest + + steps: + - uses: actions/checkout@v4 + - name: Use Node.js 20.x + uses: actions/setup-node@v4 + with: + node-version: 20.x + cache: yarn + cache-dependency-path: yarn.lock + + - name: Restore cached node_modules + uses: actions/cache@v4 + with: + path: '**/node_modules' + key: node_modules-${{ runner.arch }}-${{ runner.os }}-${{ hashFiles('yarn.lock') }} + + - name: Install deps + run: yarn install --frozen-lockfile + + - name: Lint codebase + run: yarn ci-check diff --git a/.github/workflows/textlint_lint.yml b/.github/workflows/textlint_lint.yml new file mode 100644 index 000000000..0dcf8610d --- /dev/null +++ b/.github/workflows/textlint_lint.yml @@ -0,0 +1,49 @@ +name: Textlint Lint + +on: + push: + branches: + - main + paths: + - 'src/**/*.md' + - 'textlint/**/*.js' + - '.github/workflows/textlint_lint.yml' + - 'package.json' + + pull_request: + types: + - opened + - synchronize + - reopened + paths: + - 'src/**/*.md' + - 'textlint/**/*.js' + - '.github/workflows/textlint_lint.yml' + - 'package.json' + +jobs: + Lint: + runs-on: ubuntu-latest + + steps: + - name: Set up checkout + uses: actions/checkout@v4 + + - name: Set up node + uses: actions/setup-node@v4 + with: + node-version: 20.x + cache: yarn + + - name: Set up cache + uses: actions/cache@v4 + with: + path: ~/.yarn-cache + key: ${{ runner.os }}-yarn-${{ hashFiles('**/yarn.lock') }} + + - name: Install dependencies + run: yarn install --frozen-lockfile + # The `--frozen-lockfile` flag in Yarn ensures that dependencies are installed without modifying the `yarn.lock` file. It is useful for maintaining consistency in CI/CD environments by preventing unexpected changes to the lock file and ensuring that the same versions of dependencies are installed. + + - name: Lint + run: yarn textlint-lint diff --git a/.github/workflows/textlint_test.yml b/.github/workflows/textlint_test.yml new file mode 100644 index 000000000..10af72be0 --- /dev/null +++ b/.github/workflows/textlint_test.yml @@ -0,0 +1,45 @@ +name: Textlint Test + +on: + push: + branches: + - main + paths: + - 'textlint/**/*.js' + - '.github/workflows/textlint_test.yml' + + pull_request: + types: + - opened + - synchronize + - reopened + paths: + - 'textlint/**/*.js' + - '.github/workflows/textlint_test.yml' + +jobs: + Test: + runs-on: ubuntu-latest + + steps: + - name: Set up checkout + uses: actions/checkout@v4 + + - name: Set up node + uses: actions/setup-node@v4 + with: + node-version: 20.x + cache: yarn + + - name: Set up cache + uses: actions/cache@v4 + with: + path: ~/.yarn-cache + key: ${{ runner.os }}-yarn-${{ hashFiles('**/yarn.lock') }} + + - name: Install dependencies + run: yarn install --frozen-lockfile + # The `--frozen-lockfile` flag in Yarn ensures that dependencies are installed without modifying the `yarn.lock` file. It is useful for maintaining consistency in CI/CD environments by preventing unexpected changes to the lock file and ensuring that the same versions of dependencies are installed. + + - name: Test + run: yarn textlint-test diff --git a/.gitignore b/.gitignore index e81f1af62..ff519fa0f 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,53 @@ -.cache -.DS_STORE -.idea +# See https://help.github.com/articles/ignoring-files/ for more about ignoring files. + +# dependencies node_modules -/public -yarn-error.log \ No newline at end of file +/.pnp +.pnp.js + +# testing +/coverage + +# next.js +/.next/ +/out/ + +# production +/build + +# misc +.DS_Store +*.pem +tsconfig.tsbuildinfo + +# debug +npm-debug.log* +yarn-debug.log* +yarn-error.log* + +# local env files +.env.local +.env.development.local +.env.test.local +.env.production.local + +# vercel +.vercel + +# external fonts +public/fonts/**/Optimistic_*.woff2 + +# rss +public/rss.xml + +# code editor +.cursor +.idea +*.code-workspace + +# claude local settings +.claude/*.local.* +.claude/react/ + +# worktrees +.worktrees/ diff --git a/.husky/common.sh b/.husky/common.sh new file mode 100644 index 000000000..a9390c4df --- /dev/null +++ b/.husky/common.sh @@ -0,0 +1,9 @@ +#!/bin/sh +command_exists () { + command -v "$1" >/dev/null 2>&1 +} + +# Windows 10, Git Bash and Yarn workaround +if command_exists winpty && test -t 1; then + exec < /dev/tty +fi diff --git a/.husky/pre-commit b/.husky/pre-commit new file mode 100755 index 000000000..eb6e8c1c0 --- /dev/null +++ b/.husky/pre-commit @@ -0,0 +1,5 @@ +#!/bin/sh +. "$(dirname "$0")/_/husky.sh" +. "$(dirname "$0")/common.sh" + +yarn lint-staged diff --git a/.nvmrc b/.nvmrc deleted file mode 100644 index 66df3b7ab..000000000 --- a/.nvmrc +++ /dev/null @@ -1 +0,0 @@ -12.16.1 diff --git a/.prettierignore b/.prettierignore new file mode 100644 index 000000000..8d85bc21a --- /dev/null +++ b/.prettierignore @@ -0,0 +1,2 @@ +src/content/**/*.md +src/components/MDX/Sandpack/sandpack-rsc/sandbox-code/src/worker-bundle.dist.js diff --git a/.prettierrc b/.prettierrc index eb91e6abb..19b54ad05 100644 --- a/.prettierrc +++ b/.prettierrc @@ -1,8 +1,21 @@ { "bracketSpacing": false, - "jsxBracketSameLine": true, - "parser": "flow", - "printWidth": 80, "singleQuote": true, - "trailingComma": "all" -} \ No newline at end of file + "bracketSameLine": true, + "trailingComma": "es5", + "printWidth": 80, + "overrides": [ + { + "files": "*.css", + "options": { + "parser": "css" + } + }, + { + "files": "*.md", + "options": { + "parser": "mdx" + } + } + ] +} diff --git a/.textlintrc.js b/.textlintrc.js index 4daecbbe5..fc2a0b9a5 100644 --- a/.textlintrc.js +++ b/.textlintrc.js @@ -1,6 +1,20 @@ module.exports = { + rules: { + 'allowed-uris': { + disallowed: { + /** + * Disallow URIs starting with the following strings: + * - https://ko.react.dev + * - http://ko.react.dev + * + * For example, + * `https://ko.react.dev/reference/rules` can be replaced with `/reference/rules`. + */ + links: [/https?:\/\/ko\.react\.dev/g], + }, + }, + }, filters: { comments: true, }, - formatterName: 'stylish', }; diff --git a/.vscode/extensions.json b/.vscode/extensions.json new file mode 100644 index 000000000..034db5d67 --- /dev/null +++ b/.vscode/extensions.json @@ -0,0 +1,7 @@ +{ + "recommendations": [ + "dbaeumer.vscode-eslint", + "esbenp.prettier-vscode", + "editorconfig.editorconfig" + ] +} diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 000000000..44d5ad55b --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,8 @@ +{ + "editor.formatOnSave": true, + "editor.formatOnPaste": true, + "editor.defaultFormatter": "esbenp.prettier-vscode", + "editor.codeActionsOnSave": { + "source.fixAll.eslint": "always" + } +} diff --git a/CLAUDE.md b/CLAUDE.md new file mode 100644 index 000000000..3a081e6d5 --- /dev/null +++ b/CLAUDE.md @@ -0,0 +1,52 @@ +# CLAUDE.md + +This file provides guidance to Claude Code when working with this repository. + +## Project Overview + +This is the React documentation website (react.dev), built with Next.js 15.1.11 and React 19. Documentation is written in MDX format. + +## Development Commands + +```bash +yarn build # Production build +yarn lint # Run ESLint +yarn lint:fix # Auto-fix lint issues +yarn tsc # TypeScript type checking +yarn check-all # Run prettier, lint:fix, tsc, and rss together +``` + +## Project Structure + +``` +src/ +β”œβ”€β”€ content/ # Documentation content (MDX files) +β”‚ β”œβ”€β”€ learn/ # Tutorial/learning content +β”‚ β”œβ”€β”€ reference/ # API reference docs +β”‚ β”œβ”€β”€ blog/ # Blog posts +β”‚ └── community/ # Community pages +β”œβ”€β”€ components/ # React components +β”œβ”€β”€ pages/ # Next.js pages +β”œβ”€β”€ hooks/ # Custom React hooks +β”œβ”€β”€ utils/ # Utility functions +└── styles/ # CSS/Tailwind styles +``` + +## Code Conventions + +### TypeScript/React +- Functional components only +- Tailwind CSS for styling + +### Documentation Style + +When editing files in `src/content/`, the appropriate skill will be auto-suggested: +- `src/content/learn/` - Learn page structure and tone +- `src/content/reference/` - Reference page structure and tone + +For MDX components (DeepDive, Pitfall, Note, etc.), invoke `/docs-components`. +For Sandpack code examples, invoke `/docs-sandpack`. + +See `.claude/docs/react-docs-patterns.md` for comprehensive style guidelines. + +Prettier is used for formatting (config in `.prettierrc`). diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md index f049d4c53..97c4965b8 100644 --- a/CODE_OF_CONDUCT.md +++ b/CODE_OF_CONDUCT.md @@ -1,76 +1,122 @@ -# Code of Conduct +# κΈ°μ—¬μž 행동 κ°•λ Ή κ·œμ•½ -## Our Pledge +## μ„œμ•½ -In the interest of fostering an open and welcoming environment, we as -contributors and maintainers pledge to make participation in our project and -our community a harassment-free experience for everyone, regardless of age, body -size, disability, ethnicity, sex characteristics, gender identity and expression, -level of experience, education, socio-economic status, nationality, personal -appearance, race, religion, or sexual identity and orientation. +μš°λ¦¬λŠ” ꡬ성원, κΈ°μ—¬μž 및 λ¦¬λ”λ‘œμ„œ 컀λ€λ‹ˆν‹°μ— μ°Έμ—¬ν•˜μ—¬ +μ—°λ Ή, 신체 크기, λˆˆμ— λ³΄μ΄κ±°λ‚˜ 보이지 μ•ŠλŠ” μž₯μ• , λ―Όμ‘±μ„±, 성별, μ„± 정체성과 ν‘œν˜„, +κ²½λ ₯, ν•™λ ₯, μ‚¬νšŒ 경제적 μ§€μœ„, ꡭ적, μ™Έλͺ¨, 인쒅, 카슀트 μ œλ„, 피뢀색, 쒅ꡐ +λ˜λŠ” 성적 정체성과 성적 μ„±ν–₯에 관계없이 λͺ¨λ“  μ‚¬λžŒμ„ μ°¨λ³„ν•˜μ§€ μ•Šμ„ 것을 μ„œμ•½ν•œλ‹€. -## Our Standards +μš°λ¦¬λŠ” 개방적이고 μΉœκ·Όν•˜λ©° λ‹€μ–‘ν•˜κ³  포용적이며 κ±΄κ°•ν•œ 컀λ€λ‹ˆν‹°μ— κΈ°μ—¬ν•˜λŠ” +λ°©μ‹μœΌλ‘œ ν–‰λ™ν•˜κ³  μƒν˜Έμž‘μš©ν•  것을 μ„œμ•½ν•œλ‹€. -Examples of behavior that contributes to creating a positive environment -include: +## ν‘œμ€€ -* Using welcoming and inclusive language -* Being respectful of differing viewpoints and experiences -* Gracefully accepting constructive criticism -* Focusing on what is best for the community -* Showing empathy towards other community members +컀λ€λ‹ˆν‹°μ˜ 긍정적인 ν™˜κ²½μ„ μœ„ν•΄ κΈ°μ—¬μžκ°€ ν•΄μ•Ό ν•  행동은 λ‹€μŒκ³Ό κ°™λ‹€. -Examples of unacceptable behavior by participants include: +- λ‹€λ₯Έ μ‚¬λžŒλ“€μ— λŒ€ν•œ 친절과 곡감 ν‘œν˜„ +- μ„œλ‘œ λ‹€λ₯Έ 의견 및 관점, κ²½ν—˜μ— λŒ€ν•œ 쑴쀑 +- 건섀적인 ν”Όλ“œλ°±μ„ 제곡 및 μ—΄λ¦° 마음으둜 수락 +- μ±…μž„μ„ 받아듀이고 μ‹€μˆ˜λ‘œ 인해 영ν–₯을 받은 μ‚¬λžŒλ“€μ—κ²Œ μ‚¬κ³Όν•˜λ©° κ²½ν—˜μ„ 톡해 배움 +- 개인뿐만 μ•„λ‹Œ 전체 컀λ€λ‹ˆν‹°λ₯Ό μœ„ν•œ μ΅œμ„ μ˜ 방법에 집쀑 -* The use of sexualized language or imagery and unwelcome sexual attention or - advances -* Trolling, insulting/derogatory comments, and personal or political attacks -* Public or private harassment -* Publishing others' private information, such as a physical or electronic - address, without explicit permission -* Other conduct which could reasonably be considered inappropriate in a - professional setting +ν•˜μ§€λ§μ•„μ•Ό ν•  행동은 λ‹€μŒκ³Ό κ°™λ‹€. -## Our Responsibilities +- 성적인 언어와 이미지 μ‚¬μš©, 성적 κ΄€μ‹¬μ΄λ‚˜ μ–΄λ–€ μ’…λ₯˜μ˜ μ ‘κ·Ό +- μ†Œλͺ¨μ μΈ λ…ΌμŸ, λͺ¨μš•적 λ˜λŠ” λΉ„ν•˜ν•˜λŠ” λŒ“κΈ€κ³Ό 개인적 λ˜λŠ” μ •μΉ˜μ μΈ 곡격 +- κ³΅κ°œμ μ΄κ±°λ‚˜ 개인적인 괴둭힘 +- λ™μ˜μ—†λŠ” μ§‘μ£Όμ†Œ λ˜λŠ” 이메일 μ£Όμ†Œ λ“±μ˜ 개인 μ •λ³΄μ˜ 곡개 +- λΆ€μ μ ˆν•œ κ²ƒμœΌλ‘œ 간주될 수 μžˆλŠ” λ‹€λ₯Έ ν–‰μœ„ -Project maintainers are responsible for clarifying the standards of acceptable -behavior and are expected to take appropriate and fair corrective action in -response to any instances of unacceptable behavior. +## μ§‘ν–‰ μ±…μž„ -Project maintainers have the right and responsibility to remove, edit, or -reject comments, commits, code, wiki edits, issues, and other contributions -that are not aligned to this Code of Conduct, or to ban temporarily or -permanently any contributor for other behaviors that they deem inappropriate, -threatening, offensive, or harmful. +컀λ€λ‹ˆν‹° λ¦¬λ”λŠ” ν—ˆμš©λ˜λŠ” ν–‰λ™μ˜ 기쀀을 λͺ…ν™•νžˆ ν•˜κ³  μ§‘ν–‰ν•  μ±…μž„μ΄ 있으며 +λΆ€μ μ ˆν•˜λ‹€κ³  μ—¬κ²¨μ§€λŠ” λͺ¨λ“  행동, μœ„ν˜‘, 곡격 λ˜λŠ” 피해에 λŒ€ν•΄ μ μ ˆν•˜κ³  +κ³΅μ •ν•œ 행동을 μ·¨ν•œλ‹€. -## Scope +ν”„λ‘œμ νŠΈ μœ μ§€μžλŠ” 이 행동 강령을 λ”°λ₯΄μ§€ μ•Šμ€ λŒ“κΈ€, 컀밋, μ½”λ“œ, μœ„ν‚€ νŽΈμ§‘, +μ΄μŠˆμ™€ κ·Έ μ™Έ λ‹€λ₯Έ κΈ°μ—¬λ₯Ό μ‚­μ œ, μˆ˜μ • λ˜λŠ” κ±°λΆ€ν•  κΆŒλ¦¬μ™€ μ±…μž„μ΄ μžˆλ‹€. λ˜ν•œ, +λΆ€μ λ‹Ήν•˜κ±°λ‚˜ ν—˜μ•…ν•˜κ±°λ‚˜ κ³΅κ²©μ μ΄κ±°λ‚˜ ν•΄λ‘­λ‹€κ³  μƒκ°ν•˜λŠ” λ‹€λ₯Έ 행동을 ν•œ κΈ°μ—¬μžλ₯Ό +μΌμ‹œμ  λ˜λŠ” 영ꡬ적으둜 퇴μž₯μ‹œν‚¬ 수 μžˆλ‹€. -This Code of Conduct applies within all project spaces, and it also applies when -an individual is representing the project or its community in public spaces. -Examples of representing a project or community include using an official -project e-mail address, posting via an official social media account, or acting -as an appointed representative at an online or offline event. Representation of -a project may be further defined and clarified by project maintainers. +컀λ€λ‹ˆν‹° λ¦¬λ”λŠ” 이 행동 강령을 λ”°λ₯΄μ§€ μ•ŠλŠ” λŒ“κΈ€, 컀밋, μ½”λ“œ, μœ„ν‚€ νŽΈμ§‘, +μ΄μŠˆμ™€ κ·Έ μ™Έ λ‹€λ₯Έ κΈ°μ—¬λ₯Ό μ‚­μ œ, μˆ˜μ • λ˜λŠ” κ±°λΆ€ν•  κΆŒλ¦¬μ™€ μ±…μž„μ΄ 있으며, +μ μ ˆν•œ 경우 μ€‘μž¬μ  μ˜μ‚¬κ²°μ •μ— λŒ€ν•œ 이유λ₯Ό 전달할 것이닀. -## Enforcement +## λ²”μœ„ -Instances of abusive, harassing, or otherwise unacceptable behavior may be -reported by contacting the project team at . All -complaints will be reviewed and investigated and will result in a response that -is deemed necessary and appropriate to the circumstances. The project team is -obligated to maintain confidentiality with regard to the reporter of an incident. -Further details of specific enforcement policies may be posted separately. +이 행동 강령은 개인이 곡개 μ˜μ—­μ—μ„œ 컀λ€λ‹ˆν‹°λ₯Ό κ³΅μ‹μ μœΌλ‘œ λŒ€ν‘œν•  λ•Œλ₯Ό +ν¬ν•¨ν•˜μ—¬ λͺ¨λ“  컀λ€λ‹ˆν‹° μ˜μ—­μ— μ μš©λœλ‹€. +컀λ€λ‹ˆν‹° λŒ€ν‘œμ˜ 예둜 곡식 이메일 μ£Όμ†Œ μ‚¬μš©, 곡식 μ†Œμ…œ λ―Έλ””μ–΄ 계정을 ν†΅ν•œ κ²Œμ‹œ, +온/μ˜€ν”„λΌμΈ μ΄λ²€νŠΈμ—μ„œ μž„λͺ…λœ λŒ€ν‘œμžμ˜ ν™œλ™μ΄ μžˆλ‹€. -Project maintainers who do not follow or enforce the Code of Conduct in good -faith may face temporary or permanent repercussions as determined by other -members of the project's leadership. +## μ§‘ν–‰ -## Attribution +λͺ¨μš•μ μ΄κ±°λ‚˜ 괴둭힘 λ˜λŠ” κ·Έ μ™Έ ν•˜μ§€λ§μ•„μ•Ό ν•  행동을 λ°œκ²¬ν•˜λ©΄ +을 톡해 μ§‘ν–‰ μ±…μž„μ΄ μžˆλŠ” 컀λ€λ‹ˆν‹° λ¦¬λ”μ—κ²Œ λ³΄κ³ ν•œλ‹€. +λͺ¨λ“  λΆˆλ§Œμ‚¬ν•­μ€ μ‹ μ†ν•˜κ³  κ³΅μ •ν•˜κ²Œ κ²€ν† λ˜κ³  쑰사될 것이닀. -This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, -available at https://www.contributor-covenant.org/version/1/4/code-of-conduct.html +컀λ€λ‹ˆν‹° λ¦¬λ”λŠ” μ‚¬κ±΄μ˜ 보고자의 μ‚¬μƒν™œκ³Ό μ•ˆμ „μ„ 쑴쀑할 μ˜λ¬΄κ°€ μžˆλ‹€. -[homepage]: https://www.contributor-covenant.org +## μ§‘ν–‰ μ§€μΉ¨ + +컀λ€λ‹ˆν‹° λ¦¬λ”λŠ” 행동 κ°•λ Ή μœ„λ°˜μœΌλ‘œ κ°„μ£Όλ˜λŠ” 행동에 λŒ€ν•œ κ²°κ³Όλ₯Ό κ²°μ •ν•  λ•Œ, +λ‹€μŒμ˜ 컀λ€λ‹ˆν‹° 영ν–₯ 지침을 μ€€μˆ˜ν•œλ‹€: + +### 1. μ •μ • + +**컀λ€λ‹ˆν‹° 영ν–₯**: 컀λ€λ‹ˆν‹° λ‚΄ λΆ€μ μ ˆν•œ μ–Έμ–΄ μ‚¬μš©μ΄λ‚˜ +비전문적인 행동 λ˜λŠ” λΆˆμΎŒν•¨μ„ μ£ΌλŠ” 행동. + +**κ²°κ³Ό**: 컀λ€λ‹ˆν‹° 리더가 λ³„λ„λ‘œ μœ„λ°˜μ— λŒ€ν•œ λͺ…ν™•μ„±κ³Ό λΆ€μ μ ˆν•¨μ— λŒ€ν•œ +이유λ₯Ό μ„€λͺ…ν•˜κ³  μ„œλ©΄ κ²½κ³ . +곡개 사과λ₯Ό μš”μ²­ν•  수 μžˆλ‹€. + +### 2. κ²½κ³  + +**컀λ€λ‹ˆν‹° 영ν–₯**: 단일 사고 λ˜λŠ” μ—°μ†λœ 행동 μœ„λ°˜. + +**κ²°κ³Ό**: 지속적인 행동에 λŒ€ν•œ 결과에 λŒ€ν•΄ κ²½κ³ . +νŠΉμ • κΈ°κ°„λ™μ•ˆ 행동 강령을 μ‹œν–‰ν•˜λŠ” μ‚¬λžŒλ“€κ³Όμ˜ μ›μΉ˜ μ•ŠλŠ” μƒν˜Έμž‘μš©μ„ ν¬ν•¨ν•œ +κ΄€λ ¨λœ μ‚¬λžŒλ“€κ³Όμ˜ μƒν˜Έμž‘μš© κΈˆμ§€. μ†Œμ…œ 미디어와 같은 μ™ΈλΆ€ μ±„λ„λΏλ§Œ μ•„λ‹Œ +컀λ€λ‹ˆν‹° κ³΅κ°„μ—μ„œμ˜ μƒν˜Έμž‘μš©λ„ κΈˆμ§€λœλ‹€. +이 쑰항을 μœ„λ°˜ν•˜λ©΄ μΌμ‹œμ  ν˜Ήμ€ 영ꡬ적으둜 제재둜 μ΄μ–΄μ§ˆ 수 μžˆλ‹€. + +### 3. μΌμ‹œμ μΈ 제재 + +**컀λ€λ‹ˆν‹° 영ν–₯**: μ§€μ†μ μœΌλ‘œ λΆ€μ μ ˆν•œ 행동을 ν¬ν•¨ν•œ +μ‹¬κ°ν•œ 컀λ€λ‹ˆν‹° κΈ°μ€€ μœ„λ°˜. -For answers to common questions about this code of conduct, see -https://www.contributor-covenant.org/faq +**κ²°κ³Ό**: νŠΉμ • κΈ°κ°„λ™μ•ˆ 컀λ€λ‹ˆν‹°μ™€μ˜ μ–΄λ– ν•œ μ’…λ₯˜μ˜ μƒν˜Έμž‘μš©μ΄λ‚˜ +곡개적 μ†Œν†΅μ΄ μΌμ‹œμ  제재. +이 κΈ°κ°„λ™μ•ˆ 행동 강령을 μ‹œν–‰ν•˜λŠ” μ‚¬λžŒλ“€κ³Όμ˜ μ›μΉ˜ μ•ŠλŠ” μƒν˜Έμž‘μš©μ„ ν¬ν•¨ν•œ +κ΄€λ ¨λœ μ‚¬λžŒλ“€κ³Όμ˜ μƒν˜Έμž‘μš© κΈˆμ§€. μ†Œμ…œ 미디어와 같은 μ™ΈλΆ€ μ±„λ„λΏλ§Œ μ•„λ‹Œ +컀λ€λ‹ˆν‹° κ³΅κ°„μ—μ„œμ˜ μƒν˜Έμž‘μš©λ„ κΈˆμ§€λœλ‹€. +이 쑰항을 μœ„λ°˜ν•˜λ©΄ μΌμ‹œμ  ν˜Ήμ€ 영ꡬ적으둜 제재둜 μ΄μ–΄μ§ˆ 수 μžˆλ‹€. + +### 4. 영ꡬ 제재 + +**컀λ€λ‹ˆν‹° 영ν–₯**: 지속적인 λΆ€μ μ ˆν•œ 행동, 개인적인 괴둭힘 λ˜λŠ” +개인의 계급에 λŒ€ν•œ κ³΅κ²©μ΄λ‚˜ ν„ν•˜λ₯Ό ν¬ν•¨ν•œ 컀λ€λ‹ˆν‹° ν‘œμ€€ μœ„λ°˜ νŒ¨ν„΄μ„ λ³΄μž„. + +**κ²°κ³Ό**: 컀λ€λ‹ˆν‹°μ™€μ˜ λͺ¨λ“  μ’…λ₯˜μ˜ 곡개적 ꡐλ₯˜λ₯Ό 영ꡬ적으둜 제재. + +## μ°Έκ³  + +이 행동 강령은 [κΈ°μ—¬μž κ·œμ•½][homepage] 의 2.1 버전을 λ³€ν˜•ν•˜μ˜€μŠ΅λ‹ˆλ‹€. κ·Έ λ‚΄μš©μ€ +[https://www.contributor-covenant.org/ko/version/2/1/code-of-conduct.html][v2.1] +μ—μ„œ 확인할 수 μžˆμŠ΅λ‹ˆλ‹€. + +컀λ€λ‹ˆν‹° 영ν–₯ 지침은 [Mozilla's code of conduct enforcement ladder][Mozilla CoC] +μ—μ„œ μ˜κ°μ„ μ–»μ—ˆμŠ΅λ‹ˆλ‹€. + +이 행동 강령에 κ΄€λ ¨ν•œ 일반적인 μ§ˆλ¬Έμ— λŒ€ν•œ λŒ€λ‹΅μ€ +[https://www.contributor-covenant.org/faq][FAQ]λ₯Ό μ°Έκ³ ν•  수 μžˆμŠ΅λ‹ˆλ‹€. +λ²ˆμ—­λ³Έμ€ [https://www.contributor-covenant.org/translations][translations]μ—μ„œ +λ³Ό 수 μžˆμŠ΅λ‹ˆλ‹€. + +[homepage]: https://www.contributor-covenant.org +[v2.1]: https://www.contributor-covenant.org/version/2/1/code_of_conduct.html +[Mozilla CoC]: https://github.com/mozilla/diversity +[FAQ]: https://www.contributor-covenant.org/faq +[translations]: https://www.contributor-covenant.org/translations diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index e10f4f53e..96229a467 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,62 +1,50 @@ -# Contributing +# κΈ°μ—¬ν•˜κΈ° -Thank you for your interest in contributing to the React Docs! +React λ¬Έμ„œ 기여에 관심을 κ°€μ Έμ£Όμ…”μ„œ κ°μ‚¬ν•©λ‹ˆλ‹€! -## Code of Conduct +## 행동 κ°•λ Ή -Facebook has adopted a Code of Conduct that we expect project -participants to adhere to. Please [read the full text](https://code.facebook.com/codeofconduct) -so that you can understand what actions will and will not be tolerated. +페이슀뢁Facebook은 ν”„λ‘œμ νŠΈ μ°Έκ°€μžκ°€ μ€€μˆ˜ν•΄μ•Ό ν•˜λŠ” 행동 강령을 μ±„νƒν–ˆμŠ΅λ‹ˆλ‹€. [전문을 μ½μ–΄λ³΄μ„Έμš”](https://code.facebook.com/codeofconduct). μ–΄λ–€ 행동이 ν—ˆμš©λ˜κ³  ν—ˆμš©λ˜μ§€ μ•ŠλŠ”μ§€ 확인할 수 μžˆμŠ΅λ‹ˆλ‹€. -## Technical Writing Tips +## 기술 λ¬Έμ„œ μž‘μ„± 팁 -This is a [good summary](https://medium.com/@kvosswinkel/coding-like-a-journalist-ee52360a16bc) for things to keep in mind when writing technical docs. +기술 λ¬Έμ„œλ₯Ό μž‘μ„±ν•  λ•Œ 염두에 두어야 ν•  사항에 λŒ€ν•œ [쒋은 μš”μ•½](https://medium.com/@kvosswinkel/coding-like-a-journalist-ee52360a16bc)μž…λ‹ˆλ‹€. -## Guidelines for Text +## 글에 λŒ€ν•œ κ°€μ΄λ“œλΌμΈ -**Different sections intentionally have different styles.** +**μ„Ήμ…˜λ§ˆλ‹€ μ˜λ„μ μœΌλ‘œ λ‹€λ₯Έ μŠ€νƒ€μΌμ„ μ‚¬μš©ν•©λ‹ˆλ‹€.** -The documentation is divided into sections to cater to different learning styles and use cases. When editing an article, try to match the surrounding text in tone and style. When creating a new article, try to match the tone of the other articles in the same section. Learn about the motivation behind each section below. +이 λ¬Έμ„œλŠ” λ‹€μ–‘ν•œ ν•™μŠ΅ μŠ€νƒ€μΌκ³Ό μ‚¬μš© 사둀λ₯Ό κ³ λ €ν•˜μ—¬ λΆ„ν• λ˜μ–΄ μžˆμŠ΅λ‹ˆλ‹€. 본문을 μˆ˜μ •ν•  λ•ŒλŠ” μ£Όλ³€ κΈ€μ˜ 톀Toneκ³Ό μŠ€νƒ€μΌStyle에 맞게 μž‘μ„±ν•˜λ„λ‘ μ£Όμ˜ν•˜μ„Έμš”. μƒˆλ‘œμš΄ 글을 μž‘μ„±ν•  λ•ŒλŠ” 같은 μ„Ήμ…˜μ— μžˆλŠ” λ‹€λ₯Έ κΈ€λ“€κ³Ό 톀을 λ§žμΆ”λ„λ‘ ν•˜μ„Έμš”. 각 μ„Ήμ…˜μ˜ μ˜λ„μ™€ λ™κΈ°λŠ” μ•„λž˜μ—μ„œ 확인할 수 μžˆμŠ΅λ‹ˆλ‹€. -**[Installation](https://reactjs.org/docs/getting-started.html)** gives an overview of the docs, and demonstrates two different ways to use it: either as a simple ` - - - - - - -
    - - - - diff --git a/beta/public/icons/logo-white.svg b/beta/public/icons/logo-white.svg deleted file mode 100644 index 7ed0e8b05..000000000 --- a/beta/public/icons/logo-white.svg +++ /dev/null @@ -1,9 +0,0 @@ - - React Logo - - - - - - - diff --git a/beta/public/icons/logo.svg b/beta/public/icons/logo.svg deleted file mode 100644 index ea77a618d..000000000 --- a/beta/public/icons/logo.svg +++ /dev/null @@ -1,9 +0,0 @@ - - React Logo - - - - - - - diff --git a/beta/public/images/blog/animal-sounds.jpg b/beta/public/images/blog/animal-sounds.jpg deleted file mode 100644 index abe6d815e..000000000 Binary files a/beta/public/images/blog/animal-sounds.jpg and /dev/null differ diff --git a/beta/public/images/blog/chatapp.png b/beta/public/images/blog/chatapp.png deleted file mode 100644 index de8c09ff3..000000000 Binary files a/beta/public/images/blog/chatapp.png and /dev/null differ diff --git a/beta/public/images/blog/cra-better-output.png b/beta/public/images/blog/cra-better-output.png deleted file mode 100644 index 44ed320ff..000000000 Binary files a/beta/public/images/blog/cra-better-output.png and /dev/null differ diff --git a/beta/public/images/blog/cra-dynamic-import.gif b/beta/public/images/blog/cra-dynamic-import.gif deleted file mode 100644 index 88db2896f..000000000 Binary files a/beta/public/images/blog/cra-dynamic-import.gif and /dev/null differ diff --git a/beta/public/images/blog/cra-jest-search.gif b/beta/public/images/blog/cra-jest-search.gif deleted file mode 100644 index ed6819d89..000000000 Binary files a/beta/public/images/blog/cra-jest-search.gif and /dev/null differ diff --git a/beta/public/images/blog/cra-pwa.png b/beta/public/images/blog/cra-pwa.png deleted file mode 100644 index 9862ae565..000000000 Binary files a/beta/public/images/blog/cra-pwa.png and /dev/null differ diff --git a/beta/public/images/blog/cra-runtime-error.gif b/beta/public/images/blog/cra-runtime-error.gif deleted file mode 100644 index 7b4405f62..000000000 Binary files a/beta/public/images/blog/cra-runtime-error.gif and /dev/null differ diff --git a/beta/public/images/blog/cra-update-exports.gif b/beta/public/images/blog/cra-update-exports.gif deleted file mode 100644 index 2820d63df..000000000 Binary files a/beta/public/images/blog/cra-update-exports.gif and /dev/null differ diff --git a/beta/public/images/blog/create-apps-with-no-configuration/compiled-successfully.png b/beta/public/images/blog/create-apps-with-no-configuration/compiled-successfully.png deleted file mode 100644 index 223f5abf2..000000000 Binary files a/beta/public/images/blog/create-apps-with-no-configuration/compiled-successfully.png and /dev/null differ diff --git a/beta/public/images/blog/create-apps-with-no-configuration/compiled-with-warnings.png b/beta/public/images/blog/create-apps-with-no-configuration/compiled-with-warnings.png deleted file mode 100644 index 20aa25e3c..000000000 Binary files a/beta/public/images/blog/create-apps-with-no-configuration/compiled-with-warnings.png and /dev/null differ diff --git a/beta/public/images/blog/create-apps-with-no-configuration/created-folder.png b/beta/public/images/blog/create-apps-with-no-configuration/created-folder.png deleted file mode 100644 index 44aff6dcd..000000000 Binary files a/beta/public/images/blog/create-apps-with-no-configuration/created-folder.png and /dev/null differ diff --git a/beta/public/images/blog/create-apps-with-no-configuration/failed-to-compile.png b/beta/public/images/blog/create-apps-with-no-configuration/failed-to-compile.png deleted file mode 100644 index a72b5fb2e..000000000 Binary files a/beta/public/images/blog/create-apps-with-no-configuration/failed-to-compile.png and /dev/null differ diff --git a/beta/public/images/blog/create-apps-with-no-configuration/npm-run-build.png b/beta/public/images/blog/create-apps-with-no-configuration/npm-run-build.png deleted file mode 100644 index a7b931e12..000000000 Binary files a/beta/public/images/blog/create-apps-with-no-configuration/npm-run-build.png and /dev/null differ diff --git a/beta/public/images/blog/devtools-component-filters.gif b/beta/public/images/blog/devtools-component-filters.gif deleted file mode 100644 index 287c66757..000000000 Binary files a/beta/public/images/blog/devtools-component-filters.gif and /dev/null differ diff --git a/beta/public/images/blog/devtools-full.gif b/beta/public/images/blog/devtools-full.gif deleted file mode 100644 index fd7ed9493..000000000 Binary files a/beta/public/images/blog/devtools-full.gif and /dev/null differ diff --git a/beta/public/images/blog/devtools-highlight-updates.png b/beta/public/images/blog/devtools-highlight-updates.png deleted file mode 100644 index 780bcf2ef..000000000 Binary files a/beta/public/images/blog/devtools-highlight-updates.png and /dev/null differ diff --git a/beta/public/images/blog/devtools-search.gif b/beta/public/images/blog/devtools-search.gif deleted file mode 100644 index 22d80051d..000000000 Binary files a/beta/public/images/blog/devtools-search.gif and /dev/null differ diff --git a/beta/public/images/blog/devtools-side-pane.gif b/beta/public/images/blog/devtools-side-pane.gif deleted file mode 100644 index 381e3554e..000000000 Binary files a/beta/public/images/blog/devtools-side-pane.gif and /dev/null differ diff --git a/beta/public/images/blog/devtools-tree-view.png b/beta/public/images/blog/devtools-tree-view.png deleted file mode 100644 index 854a39f8f..000000000 Binary files a/beta/public/images/blog/devtools-tree-view.png and /dev/null differ diff --git a/beta/public/images/blog/devtools-v4-screenshot.png b/beta/public/images/blog/devtools-v4-screenshot.png deleted file mode 100644 index 83a67d548..000000000 Binary files a/beta/public/images/blog/devtools-v4-screenshot.png and /dev/null differ diff --git a/beta/public/images/blog/dog-tutorial.png b/beta/public/images/blog/dog-tutorial.png deleted file mode 100644 index 72f8b4341..000000000 Binary files a/beta/public/images/blog/dog-tutorial.png and /dev/null differ diff --git a/beta/public/images/blog/first-look.png b/beta/public/images/blog/first-look.png deleted file mode 100644 index d36aa1f35..000000000 Binary files a/beta/public/images/blog/first-look.png and /dev/null differ diff --git a/beta/public/images/blog/flux-chart.png b/beta/public/images/blog/flux-chart.png deleted file mode 100644 index fbfdf94ea..000000000 Binary files a/beta/public/images/blog/flux-chart.png and /dev/null differ diff --git a/beta/public/images/blog/flux-diagram.png b/beta/public/images/blog/flux-diagram.png deleted file mode 100644 index 69cf64e0b..000000000 Binary files a/beta/public/images/blog/flux-diagram.png and /dev/null differ diff --git a/beta/public/images/blog/genesis_skeleton.png b/beta/public/images/blog/genesis_skeleton.png deleted file mode 100644 index 4b7c51e29..000000000 Binary files a/beta/public/images/blog/genesis_skeleton.png and /dev/null differ diff --git a/beta/public/images/blog/gpu-cursor-move.gif b/beta/public/images/blog/gpu-cursor-move.gif deleted file mode 100644 index b3a621f78..000000000 Binary files a/beta/public/images/blog/gpu-cursor-move.gif and /dev/null differ diff --git a/beta/public/images/blog/guess_filter.jpg b/beta/public/images/blog/guess_filter.jpg deleted file mode 100644 index 1983df1c8..000000000 Binary files a/beta/public/images/blog/guess_filter.jpg and /dev/null differ diff --git a/beta/public/images/blog/hacker-news-react-native.png b/beta/public/images/blog/hacker-news-react-native.png deleted file mode 100644 index a65679aba..000000000 Binary files a/beta/public/images/blog/hacker-news-react-native.png and /dev/null differ diff --git a/beta/public/images/blog/highlight-updates-example.gif b/beta/public/images/blog/highlight-updates-example.gif deleted file mode 100644 index ab0c87d0c..000000000 Binary files a/beta/public/images/blog/highlight-updates-example.gif and /dev/null differ diff --git a/beta/public/images/blog/introducing-the-react-profiler/commit-selector.png b/beta/public/images/blog/introducing-the-react-profiler/commit-selector.png deleted file mode 100644 index 9c027444d..000000000 Binary files a/beta/public/images/blog/introducing-the-react-profiler/commit-selector.png and /dev/null differ diff --git a/beta/public/images/blog/introducing-the-react-profiler/component-chart.png b/beta/public/images/blog/introducing-the-react-profiler/component-chart.png deleted file mode 100644 index 3a3615db2..000000000 Binary files a/beta/public/images/blog/introducing-the-react-profiler/component-chart.png and /dev/null differ diff --git a/beta/public/images/blog/introducing-the-react-profiler/devtools-profiler-tab.png b/beta/public/images/blog/introducing-the-react-profiler/devtools-profiler-tab.png deleted file mode 100644 index eabb3e500..000000000 Binary files a/beta/public/images/blog/introducing-the-react-profiler/devtools-profiler-tab.png and /dev/null differ diff --git a/beta/public/images/blog/introducing-the-react-profiler/filtering-commits.gif b/beta/public/images/blog/introducing-the-react-profiler/filtering-commits.gif deleted file mode 100644 index 1d73258e3..000000000 Binary files a/beta/public/images/blog/introducing-the-react-profiler/filtering-commits.gif and /dev/null differ diff --git a/beta/public/images/blog/introducing-the-react-profiler/flame-chart.png b/beta/public/images/blog/introducing-the-react-profiler/flame-chart.png deleted file mode 100644 index 80840b55c..000000000 Binary files a/beta/public/images/blog/introducing-the-react-profiler/flame-chart.png and /dev/null differ diff --git a/beta/public/images/blog/introducing-the-react-profiler/interactions-for-commit.png b/beta/public/images/blog/introducing-the-react-profiler/interactions-for-commit.png deleted file mode 100644 index 8f1a14c61..000000000 Binary files a/beta/public/images/blog/introducing-the-react-profiler/interactions-for-commit.png and /dev/null differ diff --git a/beta/public/images/blog/introducing-the-react-profiler/interactions.png b/beta/public/images/blog/introducing-the-react-profiler/interactions.png deleted file mode 100644 index 5683ac94a..000000000 Binary files a/beta/public/images/blog/introducing-the-react-profiler/interactions.png and /dev/null differ diff --git a/beta/public/images/blog/introducing-the-react-profiler/navigate-between-interactions-and-commits.gif b/beta/public/images/blog/introducing-the-react-profiler/navigate-between-interactions-and-commits.gif deleted file mode 100644 index e500459c3..000000000 Binary files a/beta/public/images/blog/introducing-the-react-profiler/navigate-between-interactions-and-commits.gif and /dev/null differ diff --git a/beta/public/images/blog/introducing-the-react-profiler/no-interactions.png b/beta/public/images/blog/introducing-the-react-profiler/no-interactions.png deleted file mode 100644 index d70199fc7..000000000 Binary files a/beta/public/images/blog/introducing-the-react-profiler/no-interactions.png and /dev/null differ diff --git a/beta/public/images/blog/introducing-the-react-profiler/no-profiler-data-multi-root.png b/beta/public/images/blog/introducing-the-react-profiler/no-profiler-data-multi-root.png deleted file mode 100644 index e56fd4128..000000000 Binary files a/beta/public/images/blog/introducing-the-react-profiler/no-profiler-data-multi-root.png and /dev/null differ diff --git a/beta/public/images/blog/introducing-the-react-profiler/no-render-times-for-selected-component.png b/beta/public/images/blog/introducing-the-react-profiler/no-render-times-for-selected-component.png deleted file mode 100644 index f77b42f85..000000000 Binary files a/beta/public/images/blog/introducing-the-react-profiler/no-render-times-for-selected-component.png and /dev/null differ diff --git a/beta/public/images/blog/introducing-the-react-profiler/no-timing-data-for-commit.png b/beta/public/images/blog/introducing-the-react-profiler/no-timing-data-for-commit.png deleted file mode 100644 index 84a4dcac2..000000000 Binary files a/beta/public/images/blog/introducing-the-react-profiler/no-timing-data-for-commit.png and /dev/null differ diff --git a/beta/public/images/blog/introducing-the-react-profiler/props-and-state.gif b/beta/public/images/blog/introducing-the-react-profiler/props-and-state.gif deleted file mode 100644 index b0b05b127..000000000 Binary files a/beta/public/images/blog/introducing-the-react-profiler/props-and-state.gif and /dev/null differ diff --git a/beta/public/images/blog/introducing-the-react-profiler/ranked-chart.png b/beta/public/images/blog/introducing-the-react-profiler/ranked-chart.png deleted file mode 100644 index 01246f5e5..000000000 Binary files a/beta/public/images/blog/introducing-the-react-profiler/ranked-chart.png and /dev/null differ diff --git a/beta/public/images/blog/introducing-the-react-profiler/see-all-commits-for-a-fiber.gif b/beta/public/images/blog/introducing-the-react-profiler/see-all-commits-for-a-fiber.gif deleted file mode 100644 index dac21e249..000000000 Binary files a/beta/public/images/blog/introducing-the-react-profiler/see-all-commits-for-a-fiber.gif and /dev/null differ diff --git a/beta/public/images/blog/introducing-the-react-profiler/see-which-props-changed.gif b/beta/public/images/blog/introducing-the-react-profiler/see-which-props-changed.gif deleted file mode 100644 index ae965be9b..000000000 Binary files a/beta/public/images/blog/introducing-the-react-profiler/see-which-props-changed.gif and /dev/null differ diff --git a/beta/public/images/blog/introducing-the-react-profiler/select-a-root-to-view-profiling-data.gif b/beta/public/images/blog/introducing-the-react-profiler/select-a-root-to-view-profiling-data.gif deleted file mode 100644 index b53f31025..000000000 Binary files a/beta/public/images/blog/introducing-the-react-profiler/select-a-root-to-view-profiling-data.gif and /dev/null differ diff --git a/beta/public/images/blog/introducing-the-react-profiler/start-profiling.png b/beta/public/images/blog/introducing-the-react-profiler/start-profiling.png deleted file mode 100644 index 7256474c0..000000000 Binary files a/beta/public/images/blog/introducing-the-react-profiler/start-profiling.png and /dev/null differ diff --git a/beta/public/images/blog/introducing-the-react-profiler/stop-profiling.png b/beta/public/images/blog/introducing-the-react-profiler/stop-profiling.png deleted file mode 100644 index 4ef27f333..000000000 Binary files a/beta/public/images/blog/introducing-the-react-profiler/stop-profiling.png and /dev/null differ diff --git a/beta/public/images/blog/introducing-the-react-profiler/zoom-in-and-out.gif b/beta/public/images/blog/introducing-the-react-profiler/zoom-in-and-out.gif deleted file mode 100644 index 3a8be2c9b..000000000 Binary files a/beta/public/images/blog/introducing-the-react-profiler/zoom-in-and-out.gif and /dev/null differ diff --git a/beta/public/images/blog/jsx-compiler.png b/beta/public/images/blog/jsx-compiler.png deleted file mode 100644 index 9b5e169c0..000000000 Binary files a/beta/public/images/blog/jsx-compiler.png and /dev/null differ diff --git a/beta/public/images/blog/kendoui.png b/beta/public/images/blog/kendoui.png deleted file mode 100644 index 8b18bf438..000000000 Binary files a/beta/public/images/blog/kendoui.png and /dev/null differ diff --git a/beta/public/images/blog/khan-academy-editor.png b/beta/public/images/blog/khan-academy-editor.png deleted file mode 100644 index f0413939d..000000000 Binary files a/beta/public/images/blog/khan-academy-editor.png and /dev/null differ diff --git a/beta/public/images/blog/landoflisp.png b/beta/public/images/blog/landoflisp.png deleted file mode 100644 index 42bad2d4b..000000000 Binary files a/beta/public/images/blog/landoflisp.png and /dev/null differ diff --git a/beta/public/images/blog/lights-out.png b/beta/public/images/blog/lights-out.png deleted file mode 100644 index 78c545e7e..000000000 Binary files a/beta/public/images/blog/lights-out.png and /dev/null differ diff --git a/beta/public/images/blog/makona-editor.png b/beta/public/images/blog/makona-editor.png deleted file mode 100644 index 4fc4ece99..000000000 Binary files a/beta/public/images/blog/makona-editor.png and /dev/null differ diff --git a/beta/public/images/blog/markdown_refactor.png b/beta/public/images/blog/markdown_refactor.png deleted file mode 100644 index b81679541..000000000 Binary files a/beta/public/images/blog/markdown_refactor.png and /dev/null differ diff --git a/beta/public/images/blog/modus-create.gif b/beta/public/images/blog/modus-create.gif deleted file mode 100644 index 194252ad1..000000000 Binary files a/beta/public/images/blog/modus-create.gif and /dev/null differ diff --git a/beta/public/images/blog/monkeys.gif b/beta/public/images/blog/monkeys.gif deleted file mode 100644 index 3da6185ce..000000000 Binary files a/beta/public/images/blog/monkeys.gif and /dev/null differ diff --git a/beta/public/images/blog/ngreact.png b/beta/public/images/blog/ngreact.png deleted file mode 100644 index 6ce7e3418..000000000 Binary files a/beta/public/images/blog/ngreact.png and /dev/null differ diff --git a/beta/public/images/blog/om-backbone.png b/beta/public/images/blog/om-backbone.png deleted file mode 100644 index df411b280..000000000 Binary files a/beta/public/images/blog/om-backbone.png and /dev/null differ diff --git a/beta/public/images/blog/parse-react.jpg b/beta/public/images/blog/parse-react.jpg deleted file mode 100644 index 15e45d2ae..000000000 Binary files a/beta/public/images/blog/parse-react.jpg and /dev/null differ diff --git a/beta/public/images/blog/polarr.jpg b/beta/public/images/blog/polarr.jpg deleted file mode 100644 index 1cfb3cc90..000000000 Binary files a/beta/public/images/blog/polarr.jpg and /dev/null differ diff --git a/beta/public/images/blog/propeller-logo.png b/beta/public/images/blog/propeller-logo.png deleted file mode 100644 index 81cfaa181..000000000 Binary files a/beta/public/images/blog/propeller-logo.png and /dev/null differ diff --git a/beta/public/images/blog/property-finder.png b/beta/public/images/blog/property-finder.png deleted file mode 100644 index 709448b4f..000000000 Binary files a/beta/public/images/blog/property-finder.png and /dev/null differ diff --git a/beta/public/images/blog/quiztime.png b/beta/public/images/blog/quiztime.png deleted file mode 100644 index 7021036e6..000000000 Binary files a/beta/public/images/blog/quiztime.png and /dev/null differ diff --git a/beta/public/images/blog/react-50k-mock-full.jpg b/beta/public/images/blog/react-50k-mock-full.jpg deleted file mode 100644 index 1ebac0063..000000000 Binary files a/beta/public/images/blog/react-50k-mock-full.jpg and /dev/null differ diff --git a/beta/public/images/blog/react-50k-mock.jpg b/beta/public/images/blog/react-50k-mock.jpg deleted file mode 100644 index bc2de61d4..000000000 Binary files a/beta/public/images/blog/react-50k-mock.jpg and /dev/null differ diff --git a/beta/public/images/blog/react-50k-tshirt.jpg b/beta/public/images/blog/react-50k-tshirt.jpg deleted file mode 100644 index c96b44ca5..000000000 Binary files a/beta/public/images/blog/react-50k-tshirt.jpg and /dev/null differ diff --git a/beta/public/images/blog/react-browserify-gulp.jpg b/beta/public/images/blog/react-browserify-gulp.jpg deleted file mode 100644 index d4389d6e9..000000000 Binary files a/beta/public/images/blog/react-browserify-gulp.jpg and /dev/null differ diff --git a/beta/public/images/blog/react-dev-tools.jpg b/beta/public/images/blog/react-dev-tools.jpg deleted file mode 100644 index 7eef44629..000000000 Binary files a/beta/public/images/blog/react-dev-tools.jpg and /dev/null differ diff --git a/beta/public/images/blog/react-diff-tree.png b/beta/public/images/blog/react-diff-tree.png deleted file mode 100644 index 9935e4ae1..000000000 Binary files a/beta/public/images/blog/react-diff-tree.png and /dev/null differ diff --git a/beta/public/images/blog/react-draggable.png b/beta/public/images/blog/react-draggable.png deleted file mode 100644 index c0cb61f16..000000000 Binary files a/beta/public/images/blog/react-draggable.png and /dev/null differ diff --git a/beta/public/images/blog/react-hackathon.jpg b/beta/public/images/blog/react-hackathon.jpg deleted file mode 100644 index 2537d9865..000000000 Binary files a/beta/public/images/blog/react-hackathon.jpg and /dev/null differ diff --git a/beta/public/images/blog/react-page.png b/beta/public/images/blog/react-page.png deleted file mode 100644 index 3249fb370..000000000 Binary files a/beta/public/images/blog/react-page.png and /dev/null differ diff --git a/beta/public/images/blog/react-perf-chrome-timeline.png b/beta/public/images/blog/react-perf-chrome-timeline.png deleted file mode 100644 index e9db8acfb..000000000 Binary files a/beta/public/images/blog/react-perf-chrome-timeline.png and /dev/null differ diff --git a/beta/public/images/blog/react-php.png b/beta/public/images/blog/react-php.png deleted file mode 100644 index cb7e69abc..000000000 Binary files a/beta/public/images/blog/react-php.png and /dev/null differ diff --git a/beta/public/images/blog/react-svg-fbp.png b/beta/public/images/blog/react-svg-fbp.png deleted file mode 100644 index ef89babad..000000000 Binary files a/beta/public/images/blog/react-svg-fbp.png and /dev/null differ diff --git a/beta/public/images/blog/react-v16.13.0/hydration-warning-after.png b/beta/public/images/blog/react-v16.13.0/hydration-warning-after.png deleted file mode 100644 index 92b6c9919..000000000 Binary files a/beta/public/images/blog/react-v16.13.0/hydration-warning-after.png and /dev/null differ diff --git a/beta/public/images/blog/react-v16.13.0/hydration-warning-before.png b/beta/public/images/blog/react-v16.13.0/hydration-warning-before.png deleted file mode 100644 index 381ab8677..000000000 Binary files a/beta/public/images/blog/react-v16.13.0/hydration-warning-before.png and /dev/null differ diff --git a/beta/public/images/blog/react-v16.9.0/codemod.gif b/beta/public/images/blog/react-v16.9.0/codemod.gif deleted file mode 100644 index 955b30fdc..000000000 Binary files a/beta/public/images/blog/react-v16.9.0/codemod.gif and /dev/null differ diff --git a/beta/public/images/blog/react-v16.9.0/cwm-warning.png b/beta/public/images/blog/react-v16.9.0/cwm-warning.png deleted file mode 100644 index 3ee69d748..000000000 Binary files a/beta/public/images/blog/react-v16.9.0/cwm-warning.png and /dev/null differ diff --git a/beta/public/images/blog/react-v17-rc/react_17_delegation.png b/beta/public/images/blog/react-v17-rc/react_17_delegation.png deleted file mode 100644 index c8b23c0d6..000000000 Binary files a/beta/public/images/blog/react-v17-rc/react_17_delegation.png and /dev/null differ diff --git a/beta/public/images/blog/reactive-bookmarklet.png b/beta/public/images/blog/reactive-bookmarklet.png deleted file mode 100644 index 25351e717..000000000 Binary files a/beta/public/images/blog/reactive-bookmarklet.png and /dev/null differ diff --git a/beta/public/images/blog/reflux-flux.png b/beta/public/images/blog/reflux-flux.png deleted file mode 100644 index dad38c7d1..000000000 Binary files a/beta/public/images/blog/reflux-flux.png and /dev/null differ diff --git a/beta/public/images/blog/relay-components/relay-architecture.png b/beta/public/images/blog/relay-components/relay-architecture.png deleted file mode 100644 index 0cfbff0d8..000000000 Binary files a/beta/public/images/blog/relay-components/relay-architecture.png and /dev/null differ diff --git a/beta/public/images/blog/relay-components/relay-containers-data-flow.png b/beta/public/images/blog/relay-components/relay-containers-data-flow.png deleted file mode 100644 index 2f062dd65..000000000 Binary files a/beta/public/images/blog/relay-components/relay-containers-data-flow.png and /dev/null differ diff --git a/beta/public/images/blog/relay-components/relay-containers.png b/beta/public/images/blog/relay-components/relay-containers.png deleted file mode 100644 index be7dee719..000000000 Binary files a/beta/public/images/blog/relay-components/relay-containers.png and /dev/null differ diff --git a/beta/public/images/blog/relay-components/sample-newsfeed.png b/beta/public/images/blog/relay-components/sample-newsfeed.png deleted file mode 100644 index 0e7f5b5de..000000000 Binary files a/beta/public/images/blog/relay-components/sample-newsfeed.png and /dev/null differ diff --git a/beta/public/images/blog/relay-visual-architecture-tour.png b/beta/public/images/blog/relay-visual-architecture-tour.png deleted file mode 100644 index b35c4978f..000000000 Binary files a/beta/public/images/blog/relay-visual-architecture-tour.png and /dev/null differ diff --git a/beta/public/images/blog/release-script-build-confirmation.png b/beta/public/images/blog/release-script-build-confirmation.png deleted file mode 100644 index 02026d172..000000000 Binary files a/beta/public/images/blog/release-script-build-confirmation.png and /dev/null differ diff --git a/beta/public/images/blog/release-script-build-overview.png b/beta/public/images/blog/release-script-build-overview.png deleted file mode 100644 index d726be464..000000000 Binary files a/beta/public/images/blog/release-script-build-overview.png and /dev/null differ diff --git a/beta/public/images/blog/release-script-publish-confirmation.png b/beta/public/images/blog/release-script-publish-confirmation.png deleted file mode 100644 index e05e64830..000000000 Binary files a/beta/public/images/blog/release-script-publish-confirmation.png and /dev/null differ diff --git a/beta/public/images/blog/resistance-calculator.png b/beta/public/images/blog/resistance-calculator.png deleted file mode 100644 index 16e8b3536..000000000 Binary files a/beta/public/images/blog/resistance-calculator.png and /dev/null differ diff --git a/beta/public/images/blog/skills-matter.png b/beta/public/images/blog/skills-matter.png deleted file mode 100644 index 4a4858c3d..000000000 Binary files a/beta/public/images/blog/skills-matter.png and /dev/null differ diff --git a/beta/public/images/blog/snake.png b/beta/public/images/blog/snake.png deleted file mode 100644 index 96d72b38a..000000000 Binary files a/beta/public/images/blog/snake.png and /dev/null differ diff --git a/beta/public/images/blog/steve_reverse.gif b/beta/public/images/blog/steve_reverse.gif deleted file mode 100644 index a442fbbd9..000000000 Binary files a/beta/public/images/blog/steve_reverse.gif and /dev/null differ diff --git a/beta/public/images/blog/strict-mode-unsafe-lifecycles-warning.png b/beta/public/images/blog/strict-mode-unsafe-lifecycles-warning.png deleted file mode 100644 index fbdeccde6..000000000 Binary files a/beta/public/images/blog/strict-mode-unsafe-lifecycles-warning.png and /dev/null differ diff --git a/beta/public/images/blog/sweet-jsx.png b/beta/public/images/blog/sweet-jsx.png deleted file mode 100644 index f20aeede4..000000000 Binary files a/beta/public/images/blog/sweet-jsx.png and /dev/null differ diff --git a/beta/public/images/blog/tcomb-react-native.png b/beta/public/images/blog/tcomb-react-native.png deleted file mode 100644 index 98120c758..000000000 Binary files a/beta/public/images/blog/tcomb-react-native.png and /dev/null differ diff --git a/beta/public/images/blog/thinking-in-react-components.png b/beta/public/images/blog/thinking-in-react-components.png deleted file mode 100644 index c71a86bcb..000000000 Binary files a/beta/public/images/blog/thinking-in-react-components.png and /dev/null differ diff --git a/beta/public/images/blog/thinking-in-react-mock.png b/beta/public/images/blog/thinking-in-react-mock.png deleted file mode 100644 index 78bd00a4a..000000000 Binary files a/beta/public/images/blog/thinking-in-react-mock.png and /dev/null differ diff --git a/beta/public/images/blog/todomvc.png b/beta/public/images/blog/todomvc.png deleted file mode 100644 index ee78eb1cd..000000000 Binary files a/beta/public/images/blog/todomvc.png and /dev/null differ diff --git a/beta/public/images/blog/turboreact.png b/beta/public/images/blog/turboreact.png deleted file mode 100644 index e8ef8cd3a..000000000 Binary files a/beta/public/images/blog/turboreact.png and /dev/null differ diff --git a/beta/public/images/blog/tutsplus.png b/beta/public/images/blog/tutsplus.png deleted file mode 100644 index 771653086..000000000 Binary files a/beta/public/images/blog/tutsplus.png and /dev/null differ diff --git a/beta/public/images/blog/unite.png b/beta/public/images/blog/unite.png deleted file mode 100644 index ab45a5355..000000000 Binary files a/beta/public/images/blog/unite.png and /dev/null differ diff --git a/beta/public/images/blog/versioning-1.png b/beta/public/images/blog/versioning-1.png deleted file mode 100644 index c13f98fd1..000000000 Binary files a/beta/public/images/blog/versioning-1.png and /dev/null differ diff --git a/beta/public/images/blog/versioning-2.png b/beta/public/images/blog/versioning-2.png deleted file mode 100644 index 39de2a010..000000000 Binary files a/beta/public/images/blog/versioning-2.png and /dev/null differ diff --git a/beta/public/images/blog/versioning-3.png b/beta/public/images/blog/versioning-3.png deleted file mode 100644 index 1824e89a9..000000000 Binary files a/beta/public/images/blog/versioning-3.png and /dev/null differ diff --git a/beta/public/images/blog/versioning-4.png b/beta/public/images/blog/versioning-4.png deleted file mode 100644 index 13ba32e39..000000000 Binary files a/beta/public/images/blog/versioning-4.png and /dev/null differ diff --git a/beta/public/images/blog/versioning-5.png b/beta/public/images/blog/versioning-5.png deleted file mode 100644 index 542a3926b..000000000 Binary files a/beta/public/images/blog/versioning-5.png and /dev/null differ diff --git a/beta/public/images/blog/versioning-6.png b/beta/public/images/blog/versioning-6.png deleted file mode 100644 index e82bc7136..000000000 Binary files a/beta/public/images/blog/versioning-6.png and /dev/null differ diff --git a/beta/public/images/blog/versioning-poll.png b/beta/public/images/blog/versioning-poll.png deleted file mode 100644 index 8b3e18d93..000000000 Binary files a/beta/public/images/blog/versioning-poll.png and /dev/null differ diff --git a/beta/public/images/blog/warn-legacy-context-in-strict-mode.png b/beta/public/images/blog/warn-legacy-context-in-strict-mode.png deleted file mode 100644 index e061325ac..000000000 Binary files a/beta/public/images/blog/warn-legacy-context-in-strict-mode.png and /dev/null differ diff --git a/beta/public/images/blog/weather.png b/beta/public/images/blog/weather.png deleted file mode 100644 index 90c5e6fea..000000000 Binary files a/beta/public/images/blog/weather.png and /dev/null differ diff --git a/beta/public/images/blog/wolfenstein_react.png b/beta/public/images/blog/wolfenstein_react.png deleted file mode 100644 index 98241b864..000000000 Binary files a/beta/public/images/blog/wolfenstein_react.png and /dev/null differ diff --git a/beta/public/images/blog/xoxo2013.png b/beta/public/images/blog/xoxo2013.png deleted file mode 100644 index d35989095..000000000 Binary files a/beta/public/images/blog/xoxo2013.png and /dev/null differ diff --git a/beta/public/images/blog/xreact.png b/beta/public/images/blog/xreact.png deleted file mode 100644 index ba23489d5..000000000 Binary files a/beta/public/images/blog/xreact.png and /dev/null differ diff --git a/beta/public/images/docs/blur-popover-close.gif b/beta/public/images/docs/blur-popover-close.gif deleted file mode 100644 index fefc6b8a4..000000000 Binary files a/beta/public/images/docs/blur-popover-close.gif and /dev/null differ diff --git a/beta/public/images/docs/cdn-cors-header.png b/beta/public/images/docs/cdn-cors-header.png deleted file mode 100644 index 31b047cbd..000000000 Binary files a/beta/public/images/docs/cdn-cors-header.png and /dev/null differ diff --git a/beta/public/images/docs/cm-steps-simple.png b/beta/public/images/docs/cm-steps-simple.png deleted file mode 100644 index e5683f9e6..000000000 Binary files a/beta/public/images/docs/cm-steps-simple.png and /dev/null differ diff --git a/beta/public/images/docs/codewinds-004.png b/beta/public/images/docs/codewinds-004.png deleted file mode 100644 index 6c4bc997f..000000000 Binary files a/beta/public/images/docs/codewinds-004.png and /dev/null differ diff --git a/beta/public/images/docs/devtools-dev.png b/beta/public/images/docs/devtools-dev.png deleted file mode 100644 index 5347b4b8d..000000000 Binary files a/beta/public/images/docs/devtools-dev.png and /dev/null differ diff --git a/beta/public/images/docs/devtools-prod.png b/beta/public/images/docs/devtools-prod.png deleted file mode 100644 index 4e200fb48..000000000 Binary files a/beta/public/images/docs/devtools-prod.png and /dev/null differ diff --git a/beta/public/images/docs/error-boundaries-stack-trace-line-numbers.png b/beta/public/images/docs/error-boundaries-stack-trace-line-numbers.png deleted file mode 100644 index db828905a..000000000 Binary files a/beta/public/images/docs/error-boundaries-stack-trace-line-numbers.png and /dev/null differ diff --git a/beta/public/images/docs/error-boundaries-stack-trace.png b/beta/public/images/docs/error-boundaries-stack-trace.png deleted file mode 100644 index f0d49d903..000000000 Binary files a/beta/public/images/docs/error-boundaries-stack-trace.png and /dev/null differ diff --git a/beta/public/images/docs/granular-dom-updates.gif b/beta/public/images/docs/granular-dom-updates.gif deleted file mode 100644 index 1651b0dae..000000000 Binary files a/beta/public/images/docs/granular-dom-updates.gif and /dev/null differ diff --git a/beta/public/images/docs/illustrations/i_browser-paint.png b/beta/public/images/docs/illustrations/i_browser-paint.png deleted file mode 100644 index b0d61fa8f..000000000 Binary files a/beta/public/images/docs/illustrations/i_browser-paint.png and /dev/null differ diff --git a/beta/public/images/docs/illustrations/i_children-prop.png b/beta/public/images/docs/illustrations/i_children-prop.png deleted file mode 100644 index 296c626dc..000000000 Binary files a/beta/public/images/docs/illustrations/i_children-prop.png and /dev/null differ diff --git a/beta/public/images/docs/illustrations/i_declarative-ui-programming.png b/beta/public/images/docs/illustrations/i_declarative-ui-programming.png deleted file mode 100644 index 206d73e51..000000000 Binary files a/beta/public/images/docs/illustrations/i_declarative-ui-programming.png and /dev/null differ diff --git a/beta/public/images/docs/illustrations/i_html_js.svg b/beta/public/images/docs/illustrations/i_html_js.svg deleted file mode 100644 index 9b6f5bad8..000000000 --- a/beta/public/images/docs/illustrations/i_html_js.svg +++ /dev/null @@ -1,95 +0,0 @@ - - - - - - - - - onSubmit() { ... } - - - - login() { ... } - - - - onClick() { ... } - - JS - - - - - - - - <div> - - - - <form> - - - - <p> - - HTML - - diff --git a/beta/public/images/docs/illustrations/i_imperative-ui-programming.png b/beta/public/images/docs/illustrations/i_imperative-ui-programming.png deleted file mode 100644 index 1e3b5fdd8..000000000 Binary files a/beta/public/images/docs/illustrations/i_imperative-ui-programming.png and /dev/null differ diff --git a/beta/public/images/docs/illustrations/i_inputs1.png b/beta/public/images/docs/illustrations/i_inputs1.png deleted file mode 100644 index 35150b22d..000000000 Binary files a/beta/public/images/docs/illustrations/i_inputs1.png and /dev/null differ diff --git a/beta/public/images/docs/illustrations/i_inputs2.png b/beta/public/images/docs/illustrations/i_inputs2.png deleted file mode 100644 index f519af36e..000000000 Binary files a/beta/public/images/docs/illustrations/i_inputs2.png and /dev/null differ diff --git a/beta/public/images/docs/illustrations/i_jsx.svg b/beta/public/images/docs/illustrations/i_jsx.svg deleted file mode 100644 index 629cad665..000000000 --- a/beta/public/images/docs/illustrations/i_jsx.svg +++ /dev/null @@ -1,55 +0,0 @@ - - - - - - - - - Form() { onClick() { ... } onSubmit() { ... } <form onSubmit> <input onClick /> <input onClick /> </form> } - Form.js - - - - - - Sidebar() { isLoggedIn() { <p>Welcome</p> } else { <Form /> }} - Sidebar.js - - - diff --git a/beta/public/images/docs/illustrations/i_keys-in-trees.png b/beta/public/images/docs/illustrations/i_keys-in-trees.png deleted file mode 100644 index 55d864f9e..000000000 Binary files a/beta/public/images/docs/illustrations/i_keys-in-trees.png and /dev/null differ diff --git a/beta/public/images/docs/illustrations/i_puritea-recipe.png b/beta/public/images/docs/illustrations/i_puritea-recipe.png deleted file mode 100644 index d3a348bd5..000000000 Binary files a/beta/public/images/docs/illustrations/i_puritea-recipe.png and /dev/null differ diff --git a/beta/public/images/docs/illustrations/i_react-batching.png b/beta/public/images/docs/illustrations/i_react-batching.png deleted file mode 100644 index e213ba3ad..000000000 Binary files a/beta/public/images/docs/illustrations/i_react-batching.png and /dev/null differ diff --git a/beta/public/images/docs/illustrations/i_react-is-blind-to-ui-swap.png b/beta/public/images/docs/illustrations/i_react-is-blind-to-ui-swap.png deleted file mode 100644 index d20511be9..000000000 Binary files a/beta/public/images/docs/illustrations/i_react-is-blind-to-ui-swap.png and /dev/null differ diff --git a/beta/public/images/docs/illustrations/i_ref.png b/beta/public/images/docs/illustrations/i_ref.png deleted file mode 100644 index c391e57e4..000000000 Binary files a/beta/public/images/docs/illustrations/i_ref.png and /dev/null differ diff --git a/beta/public/images/docs/illustrations/i_render-and-commit1.png b/beta/public/images/docs/illustrations/i_render-and-commit1.png deleted file mode 100644 index d62ba5806..000000000 Binary files a/beta/public/images/docs/illustrations/i_render-and-commit1.png and /dev/null differ diff --git a/beta/public/images/docs/illustrations/i_render-and-commit2.png b/beta/public/images/docs/illustrations/i_render-and-commit2.png deleted file mode 100644 index e01d0cce7..000000000 Binary files a/beta/public/images/docs/illustrations/i_render-and-commit2.png and /dev/null differ diff --git a/beta/public/images/docs/illustrations/i_render-and-commit3.png b/beta/public/images/docs/illustrations/i_render-and-commit3.png deleted file mode 100644 index bdf58c0e0..000000000 Binary files a/beta/public/images/docs/illustrations/i_render-and-commit3.png and /dev/null differ diff --git a/beta/public/images/docs/illustrations/i_render1.png b/beta/public/images/docs/illustrations/i_render1.png deleted file mode 100644 index 3613c7691..000000000 Binary files a/beta/public/images/docs/illustrations/i_render1.png and /dev/null differ diff --git a/beta/public/images/docs/illustrations/i_render2.png b/beta/public/images/docs/illustrations/i_render2.png deleted file mode 100644 index ca53a7785..000000000 Binary files a/beta/public/images/docs/illustrations/i_render2.png and /dev/null differ diff --git a/beta/public/images/docs/illustrations/i_render3.png b/beta/public/images/docs/illustrations/i_render3.png deleted file mode 100644 index 797860a7c..000000000 Binary files a/beta/public/images/docs/illustrations/i_render3.png and /dev/null differ diff --git a/beta/public/images/docs/illustrations/i_rerender1.png b/beta/public/images/docs/illustrations/i_rerender1.png deleted file mode 100644 index e94361e7b..000000000 Binary files a/beta/public/images/docs/illustrations/i_rerender1.png and /dev/null differ diff --git a/beta/public/images/docs/illustrations/i_rerender2.png b/beta/public/images/docs/illustrations/i_rerender2.png deleted file mode 100644 index 6d85cae84..000000000 Binary files a/beta/public/images/docs/illustrations/i_rerender2.png and /dev/null differ diff --git a/beta/public/images/docs/illustrations/i_rerender3.png b/beta/public/images/docs/illustrations/i_rerender3.png deleted file mode 100644 index d589a9b93..000000000 Binary files a/beta/public/images/docs/illustrations/i_rerender3.png and /dev/null differ diff --git a/beta/public/images/docs/illustrations/i_state-snapshot1.png b/beta/public/images/docs/illustrations/i_state-snapshot1.png deleted file mode 100644 index 69bbf2b72..000000000 Binary files a/beta/public/images/docs/illustrations/i_state-snapshot1.png and /dev/null differ diff --git a/beta/public/images/docs/illustrations/i_state-snapshot2.png b/beta/public/images/docs/illustrations/i_state-snapshot2.png deleted file mode 100644 index eea48a218..000000000 Binary files a/beta/public/images/docs/illustrations/i_state-snapshot2.png and /dev/null differ diff --git a/beta/public/images/docs/illustrations/i_state-snapshot3.png b/beta/public/images/docs/illustrations/i_state-snapshot3.png deleted file mode 100644 index a393528e2..000000000 Binary files a/beta/public/images/docs/illustrations/i_state-snapshot3.png and /dev/null differ diff --git a/beta/public/images/docs/illustrations/i_ui-snapshot.png b/beta/public/images/docs/illustrations/i_ui-snapshot.png deleted file mode 100644 index d327dfc82..000000000 Binary files a/beta/public/images/docs/illustrations/i_ui-snapshot.png and /dev/null differ diff --git a/beta/public/images/docs/implementation-notes-tree.png b/beta/public/images/docs/implementation-notes-tree.png deleted file mode 100644 index 923ef5d0d..000000000 Binary files a/beta/public/images/docs/implementation-notes-tree.png and /dev/null differ diff --git a/beta/public/images/docs/javascript-jabber.png b/beta/public/images/docs/javascript-jabber.png deleted file mode 100644 index 57d63c41c..000000000 Binary files a/beta/public/images/docs/javascript-jabber.png and /dev/null differ diff --git a/beta/public/images/docs/keyboard-focus.png b/beta/public/images/docs/keyboard-focus.png deleted file mode 100644 index 65a8dc300..000000000 Binary files a/beta/public/images/docs/keyboard-focus.png and /dev/null differ diff --git a/beta/public/images/docs/outerclick-with-keyboard.gif b/beta/public/images/docs/outerclick-with-keyboard.gif deleted file mode 100644 index c82d299f8..000000000 Binary files a/beta/public/images/docs/outerclick-with-keyboard.gif and /dev/null differ diff --git a/beta/public/images/docs/outerclick-with-mouse.gif b/beta/public/images/docs/outerclick-with-mouse.gif deleted file mode 100644 index e562e0324..000000000 Binary files a/beta/public/images/docs/outerclick-with-mouse.gif and /dev/null differ diff --git a/beta/public/images/docs/perf-dom.png b/beta/public/images/docs/perf-dom.png deleted file mode 100644 index 9a843c6ca..000000000 Binary files a/beta/public/images/docs/perf-dom.png and /dev/null differ diff --git a/beta/public/images/docs/perf-exclusive.png b/beta/public/images/docs/perf-exclusive.png deleted file mode 100644 index a8ad5003c..000000000 Binary files a/beta/public/images/docs/perf-exclusive.png and /dev/null differ diff --git a/beta/public/images/docs/perf-inclusive.png b/beta/public/images/docs/perf-inclusive.png deleted file mode 100644 index e46b370aa..000000000 Binary files a/beta/public/images/docs/perf-inclusive.png and /dev/null differ diff --git a/beta/public/images/docs/perf-wasted.png b/beta/public/images/docs/perf-wasted.png deleted file mode 100644 index c73131818..000000000 Binary files a/beta/public/images/docs/perf-wasted.png and /dev/null differ diff --git a/beta/public/images/docs/react-devtools-extension.png b/beta/public/images/docs/react-devtools-extension.png deleted file mode 100644 index 6ea2aad8d..000000000 Binary files a/beta/public/images/docs/react-devtools-extension.png and /dev/null differ diff --git a/beta/public/images/docs/react-devtools-standalone.png b/beta/public/images/docs/react-devtools-standalone.png deleted file mode 100644 index 07da74137..000000000 Binary files a/beta/public/images/docs/react-devtools-standalone.png and /dev/null differ diff --git a/beta/public/images/docs/react-devtools-state.gif b/beta/public/images/docs/react-devtools-state.gif deleted file mode 100644 index c9ff6cd35..000000000 Binary files a/beta/public/images/docs/react-devtools-state.gif and /dev/null differ diff --git a/beta/public/images/docs/s_thinking-in-react_ui.png b/beta/public/images/docs/s_thinking-in-react_ui.png deleted file mode 100644 index 21802352c..000000000 Binary files a/beta/public/images/docs/s_thinking-in-react_ui.png and /dev/null differ diff --git a/beta/public/images/docs/s_thinking-in-react_ui_outline.png b/beta/public/images/docs/s_thinking-in-react_ui_outline.png deleted file mode 100644 index d38f3e19f..000000000 Binary files a/beta/public/images/docs/s_thinking-in-react_ui_outline.png and /dev/null differ diff --git a/beta/public/images/docs/should-component-update.png b/beta/public/images/docs/should-component-update.png deleted file mode 100644 index 590af60b8..000000000 Binary files a/beta/public/images/docs/should-component-update.png and /dev/null differ diff --git a/beta/public/images/docs/sketches/exports.png b/beta/public/images/docs/sketches/exports.png deleted file mode 100644 index ef60adee1..000000000 Binary files a/beta/public/images/docs/sketches/exports.png and /dev/null differ diff --git a/beta/public/images/docs/sketches/s_add-back-ui.png b/beta/public/images/docs/sketches/s_add-back-ui.png deleted file mode 100644 index 248a55073..000000000 Binary files a/beta/public/images/docs/sketches/s_add-back-ui.png and /dev/null differ diff --git a/beta/public/images/docs/sketches/s_flow-chart.jpg b/beta/public/images/docs/sketches/s_flow-chart.jpg deleted file mode 100644 index 1e5d94bd3..000000000 Binary files a/beta/public/images/docs/sketches/s_flow-chart.jpg and /dev/null differ diff --git a/beta/public/images/docs/sketches/s_jsx-to-tree.png b/beta/public/images/docs/sketches/s_jsx-to-tree.png deleted file mode 100644 index 0b7f845e2..000000000 Binary files a/beta/public/images/docs/sketches/s_jsx-to-tree.png and /dev/null differ diff --git a/beta/public/images/docs/sketches/s_keys-in-trees.png b/beta/public/images/docs/sketches/s_keys-in-trees.png deleted file mode 100644 index e35c325d5..000000000 Binary files a/beta/public/images/docs/sketches/s_keys-in-trees.png and /dev/null differ diff --git a/beta/public/images/docs/sketches/s_lifting-state-up.png b/beta/public/images/docs/sketches/s_lifting-state-up.png deleted file mode 100644 index 94ea7fcd9..000000000 Binary files a/beta/public/images/docs/sketches/s_lifting-state-up.png and /dev/null differ diff --git a/beta/public/images/docs/sketches/s_lifting-v-providing.png b/beta/public/images/docs/sketches/s_lifting-v-providing.png deleted file mode 100644 index 1bd0dd576..000000000 Binary files a/beta/public/images/docs/sketches/s_lifting-v-providing.png and /dev/null differ diff --git a/beta/public/images/docs/sketches/s_passing-functions-down.png b/beta/public/images/docs/sketches/s_passing-functions-down.png deleted file mode 100644 index 02b3983c0..000000000 Binary files a/beta/public/images/docs/sketches/s_passing-functions-down.png and /dev/null differ diff --git a/beta/public/images/docs/sketches/s_placeholder-ui.png b/beta/public/images/docs/sketches/s_placeholder-ui.png deleted file mode 100644 index a0c6cdde6..000000000 Binary files a/beta/public/images/docs/sketches/s_placeholder-ui.png and /dev/null differ diff --git a/beta/public/images/docs/sketches/s_prop-drilling.png b/beta/public/images/docs/sketches/s_prop-drilling.png deleted file mode 100644 index 90e7c48d6..000000000 Binary files a/beta/public/images/docs/sketches/s_prop-drilling.png and /dev/null differ diff --git a/beta/public/images/docs/sketches/s_providing-context.png b/beta/public/images/docs/sketches/s_providing-context.png deleted file mode 100644 index e955dfefb..000000000 Binary files a/beta/public/images/docs/sketches/s_providing-context.png and /dev/null differ diff --git a/beta/public/images/docs/sketches/s_re-rendering.jpg b/beta/public/images/docs/sketches/s_re-rendering.jpg deleted file mode 100644 index ffb5c9344..000000000 Binary files a/beta/public/images/docs/sketches/s_re-rendering.jpg and /dev/null differ diff --git a/beta/public/images/docs/sketches/s_react-batching.jpg b/beta/public/images/docs/sketches/s_react-batching.jpg deleted file mode 100644 index 4d409435a..000000000 Binary files a/beta/public/images/docs/sketches/s_react-batching.jpg and /dev/null differ diff --git a/beta/public/images/docs/sketches/s_react-dom-tree.png b/beta/public/images/docs/sketches/s_react-dom-tree.png deleted file mode 100644 index b33bf0e44..000000000 Binary files a/beta/public/images/docs/sketches/s_react-dom-tree.png and /dev/null differ diff --git a/beta/public/images/docs/sketches/s_react-is-blind-to-ui-swap.png b/beta/public/images/docs/sketches/s_react-is-blind-to-ui-swap.png deleted file mode 100644 index aacc9191a..000000000 Binary files a/beta/public/images/docs/sketches/s_react-is-blind-to-ui-swap.png and /dev/null differ diff --git a/beta/public/images/docs/sketches/s_react-ui-response.jpg b/beta/public/images/docs/sketches/s_react-ui-response.jpg deleted file mode 100644 index 01d7a8d58..000000000 Binary files a/beta/public/images/docs/sketches/s_react-ui-response.jpg and /dev/null differ diff --git a/beta/public/images/docs/sketches/s_remove-ui.png b/beta/public/images/docs/sketches/s_remove-ui.png deleted file mode 100644 index d2307cf2f..000000000 Binary files a/beta/public/images/docs/sketches/s_remove-ui.png and /dev/null differ diff --git a/beta/public/images/docs/sketches/s_state-in-tree.png b/beta/public/images/docs/sketches/s_state-in-tree.png deleted file mode 100644 index dfd5fa648..000000000 Binary files a/beta/public/images/docs/sketches/s_state-in-tree.png and /dev/null differ diff --git a/beta/public/images/docs/sketches/s_ui-component-swap.png b/beta/public/images/docs/sketches/s_ui-component-swap.png deleted file mode 100644 index 4b13e2bf3..000000000 Binary files a/beta/public/images/docs/sketches/s_ui-component-swap.png and /dev/null differ diff --git a/beta/public/images/docs/sketches/s_ui-components-swap.png b/beta/public/images/docs/sketches/s_ui-components-swap.png deleted file mode 100644 index 669e7bb88..000000000 Binary files a/beta/public/images/docs/sketches/s_ui-components-swap.png and /dev/null differ diff --git a/beta/public/images/docs/sketches/s_ui-response.jpg b/beta/public/images/docs/sketches/s_ui-response.jpg deleted file mode 100644 index 34f375ad2..000000000 Binary files a/beta/public/images/docs/sketches/s_ui-response.jpg and /dev/null differ diff --git a/beta/public/images/docs/sketches/s_ui-snapshots.jpg b/beta/public/images/docs/sketches/s_ui-snapshots.jpg deleted file mode 100644 index 647932bd2..000000000 Binary files a/beta/public/images/docs/sketches/s_ui-snapshots.jpg and /dev/null differ diff --git a/beta/public/images/docs/sketches/s_ui-state-snapshot.jpg b/beta/public/images/docs/sketches/s_ui-state-snapshot.jpg deleted file mode 100644 index 89ea4a24f..000000000 Binary files a/beta/public/images/docs/sketches/s_ui-state-snapshot.jpg and /dev/null differ diff --git a/beta/public/images/docs/sketches/s_ui-swap.png b/beta/public/images/docs/sketches/s_ui-swap.png deleted file mode 100644 index ce96d7e01..000000000 Binary files a/beta/public/images/docs/sketches/s_ui-swap.png and /dev/null differ diff --git a/beta/public/images/docs/source/i_browser-paint.psd b/beta/public/images/docs/source/i_browser-paint.psd deleted file mode 100644 index bb541e889..000000000 Binary files a/beta/public/images/docs/source/i_browser-paint.psd and /dev/null differ diff --git a/beta/public/images/docs/source/i_children-prop.psd b/beta/public/images/docs/source/i_children-prop.psd deleted file mode 100644 index 2577c0aa0..000000000 Binary files a/beta/public/images/docs/source/i_children-prop.psd and /dev/null differ diff --git a/beta/public/images/docs/source/i_declarative-ui-programming.psd b/beta/public/images/docs/source/i_declarative-ui-programming.psd deleted file mode 100644 index 3b1a9a4d1..000000000 Binary files a/beta/public/images/docs/source/i_declarative-ui-programming.psd and /dev/null differ diff --git a/beta/public/images/docs/source/i_imperative-ui-programming.psd b/beta/public/images/docs/source/i_imperative-ui-programming.psd deleted file mode 100644 index c1511b022..000000000 Binary files a/beta/public/images/docs/source/i_imperative-ui-programming.psd and /dev/null differ diff --git a/beta/public/images/docs/source/i_keys-in-trees.psd b/beta/public/images/docs/source/i_keys-in-trees.psd deleted file mode 100644 index bab04dc08..000000000 Binary files a/beta/public/images/docs/source/i_keys-in-trees.psd and /dev/null differ diff --git a/beta/public/images/docs/source/i_puritea-recipe.psd b/beta/public/images/docs/source/i_puritea-recipe.psd deleted file mode 100644 index 72a33ab30..000000000 Binary files a/beta/public/images/docs/source/i_puritea-recipe.psd and /dev/null differ diff --git a/beta/public/images/docs/source/i_react-batching.psd b/beta/public/images/docs/source/i_react-batching.psd deleted file mode 100644 index 88bcd617b..000000000 Binary files a/beta/public/images/docs/source/i_react-batching.psd and /dev/null differ diff --git a/beta/public/images/docs/source/i_react-is-blind-to-ui-swap.psd b/beta/public/images/docs/source/i_react-is-blind-to-ui-swap.psd deleted file mode 100644 index 5e422ba63..000000000 Binary files a/beta/public/images/docs/source/i_react-is-blind-to-ui-swap.psd and /dev/null differ diff --git a/beta/public/images/docs/source/i_ref.psd b/beta/public/images/docs/source/i_ref.psd deleted file mode 100644 index 12349b431..000000000 Binary files a/beta/public/images/docs/source/i_ref.psd and /dev/null differ diff --git a/beta/public/images/docs/source/i_render-commit.psd b/beta/public/images/docs/source/i_render-commit.psd deleted file mode 100644 index 99f62802a..000000000 Binary files a/beta/public/images/docs/source/i_render-commit.psd and /dev/null differ diff --git a/beta/public/images/docs/source/i_rerender.psd b/beta/public/images/docs/source/i_rerender.psd deleted file mode 100644 index 9dc83d5ed..000000000 Binary files a/beta/public/images/docs/source/i_rerender.psd and /dev/null differ diff --git a/beta/public/images/docs/source/i_rerendering.psd b/beta/public/images/docs/source/i_rerendering.psd deleted file mode 100644 index 2ba1cba58..000000000 Binary files a/beta/public/images/docs/source/i_rerendering.psd and /dev/null differ diff --git a/beta/public/images/docs/source/i_state-snapshot.psd b/beta/public/images/docs/source/i_state-snapshot.psd deleted file mode 100644 index b8d54ddcc..000000000 Binary files a/beta/public/images/docs/source/i_state-snapshot.psd and /dev/null differ diff --git a/beta/public/images/docs/source/s_inputs.psd b/beta/public/images/docs/source/s_inputs.psd deleted file mode 100644 index 60354742a..000000000 Binary files a/beta/public/images/docs/source/s_inputs.psd and /dev/null differ diff --git a/beta/public/images/docs/source/s_ui-snapshot.psd b/beta/public/images/docs/source/s_ui-snapshot.psd deleted file mode 100644 index 41c65f8fe..000000000 Binary files a/beta/public/images/docs/source/s_ui-snapshot.psd and /dev/null differ diff --git a/beta/public/images/docs/thinking-in-react-tagtree.png b/beta/public/images/docs/thinking-in-react-tagtree.png deleted file mode 100644 index 3d4db2d23..000000000 Binary files a/beta/public/images/docs/thinking-in-react-tagtree.png and /dev/null differ diff --git a/beta/public/images/external.png b/beta/public/images/external.png deleted file mode 100644 index 748a27e44..000000000 Binary files a/beta/public/images/external.png and /dev/null differ diff --git a/beta/public/images/external_2x.png b/beta/public/images/external_2x.png deleted file mode 100644 index 66230854d..000000000 Binary files a/beta/public/images/external_2x.png and /dev/null differ diff --git a/beta/public/images/g_arrow.png b/beta/public/images/g_arrow.png deleted file mode 100644 index 36258add5..000000000 Binary files a/beta/public/images/g_arrow.png and /dev/null differ diff --git a/beta/public/images/history.png b/beta/public/images/history.png deleted file mode 100644 index 4ca56a866..000000000 Binary files a/beta/public/images/history.png and /dev/null differ diff --git a/beta/public/images/noise.png b/beta/public/images/noise.png deleted file mode 100644 index 698f924f4..000000000 Binary files a/beta/public/images/noise.png and /dev/null differ diff --git a/beta/public/images/oss_logo.png b/beta/public/images/oss_logo.png deleted file mode 100644 index 3f376bee9..000000000 Binary files a/beta/public/images/oss_logo.png and /dev/null differ diff --git a/beta/public/images/search.png b/beta/public/images/search.png deleted file mode 100644 index 151377693..000000000 Binary files a/beta/public/images/search.png and /dev/null differ diff --git a/beta/public/images/team/acdlite.jpg b/beta/public/images/team/acdlite.jpg deleted file mode 100644 index ab54b793b..000000000 Binary files a/beta/public/images/team/acdlite.jpg and /dev/null differ diff --git a/beta/public/images/team/bvaughn.jpg b/beta/public/images/team/bvaughn.jpg deleted file mode 100644 index 227fe8d94..000000000 Binary files a/beta/public/images/team/bvaughn.jpg and /dev/null differ diff --git a/beta/public/images/team/gaearon.jpg b/beta/public/images/team/gaearon.jpg deleted file mode 100644 index e152143b7..000000000 Binary files a/beta/public/images/team/gaearon.jpg and /dev/null differ diff --git a/beta/public/images/team/lunaruan.jpg b/beta/public/images/team/lunaruan.jpg deleted file mode 100644 index 91daa3d17..000000000 Binary files a/beta/public/images/team/lunaruan.jpg and /dev/null differ diff --git a/beta/public/images/team/necolas.jpg b/beta/public/images/team/necolas.jpg deleted file mode 100644 index b7caaac06..000000000 Binary files a/beta/public/images/team/necolas.jpg and /dev/null differ diff --git a/beta/public/images/team/rickhanlonii.jpg b/beta/public/images/team/rickhanlonii.jpg deleted file mode 100644 index eb04614c5..000000000 Binary files a/beta/public/images/team/rickhanlonii.jpg and /dev/null differ diff --git a/beta/public/images/team/rnabors.jpg b/beta/public/images/team/rnabors.jpg deleted file mode 100644 index 4425c90db..000000000 Binary files a/beta/public/images/team/rnabors.jpg and /dev/null differ diff --git a/beta/public/images/team/salazarm.jpeg b/beta/public/images/team/salazarm.jpeg deleted file mode 100644 index 0360f208d..000000000 Binary files a/beta/public/images/team/salazarm.jpeg and /dev/null differ diff --git a/beta/public/images/team/sebmarkbage.jpg b/beta/public/images/team/sebmarkbage.jpg deleted file mode 100644 index 56a480ff4..000000000 Binary files a/beta/public/images/team/sebmarkbage.jpg and /dev/null differ diff --git a/beta/public/images/team/sethwebster.jpg b/beta/public/images/team/sethwebster.jpg deleted file mode 100644 index c665a0b00..000000000 Binary files a/beta/public/images/team/sethwebster.jpg and /dev/null differ diff --git a/beta/public/images/team/threepointone.jpg b/beta/public/images/team/threepointone.jpg deleted file mode 100644 index 9ad860171..000000000 Binary files a/beta/public/images/team/threepointone.jpg and /dev/null differ diff --git a/beta/public/images/team/trueadm.jpg b/beta/public/images/team/trueadm.jpg deleted file mode 100644 index 33a6b838f..000000000 Binary files a/beta/public/images/team/trueadm.jpg and /dev/null differ diff --git a/beta/public/images/tutorial/devtools.png b/beta/public/images/tutorial/devtools.png deleted file mode 100644 index 6c4765703..000000000 Binary files a/beta/public/images/tutorial/devtools.png and /dev/null differ diff --git a/beta/public/images/tutorial/tictac-empty.png b/beta/public/images/tutorial/tictac-empty.png deleted file mode 100644 index fabe3f034..000000000 Binary files a/beta/public/images/tutorial/tictac-empty.png and /dev/null differ diff --git a/beta/public/images/tutorial/tictac-numbers.png b/beta/public/images/tutorial/tictac-numbers.png deleted file mode 100644 index 69d163f45..000000000 Binary files a/beta/public/images/tutorial/tictac-numbers.png and /dev/null differ diff --git a/beta/public/js/jsfiddle-integration-babel.js b/beta/public/js/jsfiddle-integration-babel.js deleted file mode 100644 index 006c79c8a..000000000 --- a/beta/public/js/jsfiddle-integration-babel.js +++ /dev/null @@ -1,16 +0,0 @@ -/** - * Copyright (c) Facebook, Inc. and its affiliates. - */ - -// Do not delete or move this file. -// Many fiddles reference it so we have to keep it here. -(function() { - var tag = document.querySelector( - 'script[type="application/javascript;version=1.7"]' - ); - if (!tag || tag.textContent.indexOf('window.onload=function(){') !== -1) { - alert('Bad JSFiddle configuration, please fork the original React JSFiddle'); - } - tag.setAttribute('type', 'text/babel'); - tag.textContent = tag.textContent.replace(/^\/\/ { - const routes = []; - const blogPosts = await globby('src/pages/blog/**/*.md'); - - for (let postpath of blogPosts) { - const [year, month, day, title] = postpath - .replace('src/pages/blog/', '') - .split('/'); - - const rawStr = await fs.readFile(postpath, 'utf8'); - const {data, excerpt, content} = fm(rawStr, { - excerpt: function firstLine(file, options) { - file.excerpt = file.content.split('\n').slice(0, 2).join(' '); - }, - }); - const rendered = await markdownToHtml(excerpt.trimLeft().trim()); - - routes.unshift({ - path: postpath.replace('src/pages', ''), - date: [year, month, day].join('-'), - title: data.title, - author: data.author, - excerpt: rendered, - readingTime: readingTime(content).text, - }); - } - - const sorted = routes.sort((post1, post2) => - parseISO(post1.date) > parseISO(post2.date) ? -1 : 1 - ); - const blogManifest = { - routes: sorted, - }; - const blogRecentSidebar = { - routes: [ - { - title: 'Recent Posts', - path: '/blog', - heading: true, - routes: sorted.slice(0, 25), - }, - ], - }; - - await fs.writeFile( - path.resolve('./src/blogIndex.json'), - JSON.stringify(blogManifest, null, 2) - ); - await fs.writeFile( - path.resolve('./src/blogIndexRecent.json'), - JSON.stringify(blogRecentSidebar, null, 2) - ); - }) - .catch(console.error); diff --git a/beta/scripts/generateRSS.js b/beta/scripts/generateRSS.js deleted file mode 100644 index a08c7e2ad..000000000 --- a/beta/scripts/generateRSS.js +++ /dev/null @@ -1,46 +0,0 @@ -const RSS = require('rss'); -const fs = require('fs-extra'); -const authorsJson = require('../src/authors.json'); -const blogIndexJson = require('../src/blogIndex.json'); -const parse = require('date-fns/parse'); - -function removeFromLast(path, key) { - const i = path.lastIndexOf(key); - return i === -1 ? path : path.substring(0, i); -} - -const SITE_URL = 'https://reactjs.org'; - -function generate() { - const feed = new RSS({ - title: 'React.js Blog', - site_url: SITE_URL, - feed_url: SITE_URL + '/feed.xml', - }); - - blogIndexJson.routes.map((meta) => { - feed.item({ - title: meta.title, - guid: removeFromLast(meta.path, '.'), - url: SITE_URL + removeFromLast(meta.path, '.'), - date: parse(meta.date, 'yyyy-MM-dd', new Date()), - description: meta.description, - custom_elements: [].concat( - meta.author.map((author) => ({ - author: [{ name: authorsJson[author].name }], - })) - ), - }); - }); - - const rss = feed.xml({ indent: true }); - - fs.writeFileSync('./.next/static/feed.xml', rss); -} - -try { - generate(); -} catch (error) { - console.error('Error generating rss feed'); - throw error; -} diff --git a/beta/scripts/generateRedirects.js b/beta/scripts/generateRedirects.js deleted file mode 100644 index b6e23b58a..000000000 --- a/beta/scripts/generateRedirects.js +++ /dev/null @@ -1,81 +0,0 @@ -/** - * Copyright (c) Facebook, Inc. and its affiliates. - */ - -const resolve = require('path').resolve; -const {writeFile} = require('fs-extra'); -const readFileSync = require('fs').readFileSync; -const safeLoad = require('js-yaml').safeLoad; -const path = require('path'); -const versionsFile = resolve(__dirname, '../../content/versions.yml'); -const file = readFileSync(versionsFile, 'utf8'); -const versions = safeLoad(file); -const redirectsFilePath = path.join('vercel.json'); - -function writeRedirectsFile(redirects, redirectsFilePath) { - if (!redirects.length) { - return null; - } - - /** - * We will first read the old config to validate if the redirect already exists in the json - */ - const vercelConfigPath = resolve(__dirname, '../../vercel.json'); - const vercelConfigFile = readFileSync(vercelConfigPath); - const oldConfigContent = JSON.parse(vercelConfigFile); - /** - * Map data as vercel expects it to be - */ - - let vercelRedirects = {}; - - redirects.forEach((redirect) => { - const {fromPath, isPermanent, toPath} = redirect; - - vercelRedirects[fromPath] = { - destination: toPath, - permanent: !!isPermanent, - }; - }); - - /** - * Make sure we dont have the same redirect already - */ - oldConfigContent.redirects.forEach((data) => { - if(vercelRedirects[data.source]){ - delete vercelRedirects[data.source]; - } - }); - - /** - * Serialize the object to array of objects - */ - let newRedirects = []; - Object.keys(vercelRedirects).forEach((value) => - newRedirects.push({ - source: value, - destination: vercelRedirects[value].destination, - permanent: !!vercelRedirects[value].isPermanent, - }) - ); - - /** - * We already have a vercel.json so we spread the new contents along with old ones - */ - const newContents = { - ...oldConfigContent, - redirects: [...oldConfigContent.redirects, ...newRedirects], - }; - writeFile(redirectsFilePath, JSON.stringify(newContents, null, 2)); -} - -// versions.yml structure is [{path: string, url: string, ...}, ...] -writeRedirectsFile( - versions - .filter((version) => version.path && version.url) - .map((version) => ({ - fromPath: version.path, - toPath: version.url, - })), - redirectsFilePath -); diff --git a/beta/scripts/headingIDHelpers/generateHeadingIDs.js b/beta/scripts/headingIDHelpers/generateHeadingIDs.js deleted file mode 100644 index 0b1d627e0..000000000 --- a/beta/scripts/headingIDHelpers/generateHeadingIDs.js +++ /dev/null @@ -1,110 +0,0 @@ -/** - * Copyright (c) Facebook, Inc. and its affiliates. - */ - -// To do: Make this ESM. -// To do: properly check heading numbers (headings with the same text get -// numbered, this script doesn’t check that). - -const assert = require('assert'); -const fs = require('fs'); -const GithubSlugger = require('github-slugger'); -const walk = require('./walk'); - -let modules; - -function stripLinks(line) { - return line.replace(/\[([^\]]+)\]\([^)]+\)/, (match, p1) => p1); -} - -function addHeaderID(line, slugger) { - // check if we're a header at all - if (!line.startsWith('#')) { - return line; - } - - const match = - /^(#+\s+)(.+?)(\s*\{(?:\/\*|#)([^\}\*\/]+)(?:\*\/)?\}\s*)?$/.exec(line); - const before = match[1] + match[2]; - const proc = modules - .unified() - .use(modules.remarkParse) - .use(modules.remarkSlug); - const tree = proc.runSync(proc.parse(before)); - const head = tree.children[0]; - assert( - head && head.type === 'heading', - 'expected `' + - before + - '` to be a heading, is it using a normal space after `#`?' - ); - const autoId = head.data.id; - const existingId = match[4]; - const id = existingId || autoId; - // Ignore numbers: - const cleanExisting = existingId - ? existingId.replace(/-\d+$/, '') - : undefined; - const cleanAuto = autoId.replace(/-\d+$/, ''); - - if (cleanExisting && cleanExisting !== cleanAuto) { - console.log( - 'Note: heading `%s` has a different ID (`%s`) than what GH generates for it: `%s`:', - before, - existingId, - autoId - ); - } - - return match[1] + match[2] + ' {/*' + id + '*/}'; -} - -function addHeaderIDs(lines) { - // Sluggers should be per file - const slugger = new GithubSlugger(); - let inCode = false; - const results = []; - lines.forEach((line) => { - // Ignore code blocks - if (line.startsWith('```')) { - inCode = !inCode; - results.push(line); - return; - } - if (inCode) { - results.push(line); - return; - } - - results.push(addHeaderID(line, slugger)); - }); - return results; -} - -async function main(paths) { - paths = paths.length === 0 ? ['src/pages'] : paths; - - const [unifiedMod, remarkParseMod, remarkSlugMod] = await Promise.all([ - import('unified'), - import('remark-parse'), - import('remark-slug'), - ]); - const unified = unifiedMod.default; - const remarkParse = remarkParseMod.default; - const remarkSlug = remarkSlugMod.default; - modules = {unified, remarkParse, remarkSlug}; - const files = paths.map((path) => [...walk(path)]).flat(); - - files.forEach((file) => { - if (!(file.endsWith('.md') || file.endsWith('.mdx'))) { - return; - } - - const content = fs.readFileSync(file, 'utf8'); - const lines = content.split('\n'); - const updatedLines = addHeaderIDs(lines); - fs.writeFileSync(file, updatedLines.join('\n')); - }); -} - -module.exports = main; diff --git a/beta/scripts/headingIDHelpers/walk.js b/beta/scripts/headingIDHelpers/walk.js deleted file mode 100644 index 721274e09..000000000 --- a/beta/scripts/headingIDHelpers/walk.js +++ /dev/null @@ -1,24 +0,0 @@ -const fs = require('fs'); - -module.exports = function walk(dir) { - let results = []; - /** - * If the param is a directory we can return the file - */ - if(dir.includes('md')){ - return [dir]; - } - const list = fs.readdirSync(dir); - list.forEach(function (file) { - file = dir + '/' + file; - const stat = fs.statSync(file); - if (stat && stat.isDirectory()) { - /* Recurse into a subdirectory */ - results = results.concat(walk(file)); - } else { - /* Is a file */ - results.push(file); - } - }); - return results; -}; diff --git a/beta/scripts/migrations/migrateBlogPosts.js b/beta/scripts/migrations/migrateBlogPosts.js deleted file mode 100644 index 8b93c23ab..000000000 --- a/beta/scripts/migrations/migrateBlogPosts.js +++ /dev/null @@ -1,50 +0,0 @@ -const fs = require('fs-extra'); -const path = require('path'); -const fm = require('gray-matter'); -const globby = require('globby'); -const parse = require('date-fns/parse'); - -/** - * This script takes the gatsby blog posts directory and migrates it. - * - * In gatsby, blog posts were put in markdown files title YYYY-MM-DD-post-title.md. - * This script looks at that directory and then moves posts into folders paths - * that match the end URL structure of /blog/YYYY/MM/DD/postitle.md - * - * This allows us to use MDX in blog posts. - */ - -// I dropped them into src/pages/oldblog -// @todo remove after migration -// I am not proud of this. Also, the blog posts needed to be cleaned up for MDX, don't run this again. -Promise.resolve() - .then(async () => { - const blogManifest = {}; - const blogPosts = await globby('src/pages/oldblog/*.md'); - // console.log(blogPosts); - for (let postpath of blogPosts.sort()) { - const rawStr = await fs.readFile(postpath, 'utf8'); - // console.log(rawStr); - const {data, content} = fm(rawStr); - const cleanPath = postpath.replace('src/pages/oldblog/', ''); - const yrStr = parseInt(cleanPath.substr(0, 4), 10); // 2013-06-02 - // console.log(yrStr); - const dateStr = cleanPath.substr(0, 10); // 2013-06-02 - const postFileName = cleanPath.substr(11); - // console.log(postFileName, dateStr); - const datePath = dateStr.split('-').join('/'); - // console.log(datePath); - const newPath = './src/pages/blog/' + datePath + '/' + postFileName; - // console.log(newPath); - await fs.ensureFile(path.resolve(newPath)); - await fs.writeFile( - path.resolve(newPath), - rawStr - .replace('
    ', '
    ') - .replace('
    ', '
    ') - .replace('layout: post', '') - .replace('\nauthor', '\nlayout: Post\nauthor') - ); - } - }) - .catch(console.error); diff --git a/beta/scripts/migrations/migratePermalinks.js b/beta/scripts/migrations/migratePermalinks.js deleted file mode 100644 index ad0303d4a..000000000 --- a/beta/scripts/migrations/migratePermalinks.js +++ /dev/null @@ -1,35 +0,0 @@ -const fs = require('fs-extra'); -const path = require('path'); -const fm = require('gray-matter'); -const globby = require('globby'); - -/** - * This script ensures that every file in the docs folder is named corresponding - * to its respective frontmatter permalink. In the old site, the path of the page was set by - * the `permalink` in markdown frontmatter, and not the name of the file itself or it's id. - * In the new Next.js site, with its filesystem router, the name of the file must - * match exactly to its `permalink`. - */ -Promise.resolve() - .then(async () => { - const pages = await globby('src/pages/docs/**/*.{md,mdx}'); - for (let sourcePath of pages.sort()) { - const rawStr = await fs.readFile(sourcePath, 'utf8'); - const {data, content} = fm(rawStr); - const currentPath = sourcePath - .replace('src/pages/', '') - .replace('.md', ''); - const permalink = data.permalink.replace('.html', ''); - if (permalink !== currentPath) { - const destPath = 'src/pages/' + permalink + '.md'; - try { - await fs.move(sourcePath, destPath); - console.log(`MOVED: ${sourcePath} --> ${destPath}`); - } catch (error) { - console.error(`ERROR: ${sourcePath} --> ${destPath}`); - console.error(error); - } - } - } - }) - .catch(console.error); diff --git a/beta/scripts/migrations/migrateRedirects.js b/beta/scripts/migrations/migrateRedirects.js deleted file mode 100644 index 5e0a6ed0e..000000000 --- a/beta/scripts/migrations/migrateRedirects.js +++ /dev/null @@ -1,117 +0,0 @@ -const fs = require('fs-extra'); -const path = require('path'); -const fm = require('gray-matter'); -const globby = require('globby'); - -/** - * This script takes a look at all the redirect frontmatter and converts it - * into a Next.js compatible redirects list. It also merges it with netlify's - * _redirects, which we moved by hand below. - * - * @remarks - * In the old gatsby site, redirects were specified in docs and blog post - * frontmatter that looks like: - * - * --- - * redirect_from: - * - /docs/old-path.html#maybe-an-anchor - * --- - */ - -const netlifyRedirects = [ - { - source: '/html-jsx.html', - destination: 'https://magic.reactjs.net/htmltojsx.htm', - permanent: true, - }, - { - source: '/tips/controlled-input-null-value.html', - destination: '/docs/forms.html#controlled-input-null-value', - permanent: false, // @todo why were these not permanent on netlify? - }, - { - source: '/concurrent', - destination: '/docs/concurrent-mode-intro.html', - permanent: false, - }, - { - source: '/hooks', - destination: '/docs/hooks-intro.html', - permanent: false, - }, - { - source: '/tutorial', - destination: '/tutorial/tutorial.html', - permanent: false, - }, - { - source: '/your-story', - destination: 'https://www.surveymonkey.co.uk/r/MVQV2R9', - permanent: true, - }, - { - source: '/stories', - destination: 'https://medium.com/react-community-stories', - permanent: true, - }, -]; - -Promise.resolve() - .then(async () => { - let contentRedirects = []; - let redirectPageCount = 0; - - // Get all markdown pages - const pages = await globby('src/pages/**/*.{md,mdx}'); - for (let filepath of pages) { - // Read file as string - const rawStr = await fs.readFile(filepath, 'utf8'); - // Extract frontmatter - const {data, content} = fm(rawStr); - // Look for redirect yaml - if (data.redirect_from) { - redirectPageCount++; - - let destinationPath = filepath - .replace('src/pages', '') - .replace('.md', ''); - - // Fix /docs/index -> /docs - if (destinationPath === '/docs/index') { - destinationPath = '/docs'; - } - - if (destinationPath === '/index') { - destinationPath = '/'; - } - - for (let sourcePath of data.redirect_from) { - contentRedirects.push({ - source: '/' + sourcePath, // add slash - destination: destinationPath, - permanent: true, - }); - } - } - } - console.log( - `Found ${redirectPageCount} pages with \`redirect_from\` frontmatter` - ); - console.log( - `Writing ${contentRedirects.length} redirects to redirects.json` - ); - - await fs.writeFile( - path.resolve('./src/redirects.json'), - JSON.stringify( - { - redirects: [...contentRedirects, ...netlifyRedirects], - }, - null, - 2 - ) - ); - - console.log('βœ… Done writing redirects'); - }) - .catch(console.error); diff --git a/beta/src/authors.json b/beta/src/authors.json deleted file mode 100644 index 76cd5aedd..000000000 --- a/beta/src/authors.json +++ /dev/null @@ -1,130 +0,0 @@ -{ - "acdlite": { - "name": "Andrew Clark", - "url": "https://twitter.com/acdlite" - }, - "benigeri": { - "name": "Paul Benigeri", - "url": "https://github.com/benigeri" - }, - "bvaughn": { - "name": "Brian Vaughn", - "url": "https://github.com/bvaughn" - }, - "chenglou": { - "name": "Cheng Lou", - "url": "https://twitter.com/_chenglou" - }, - "clemmy": { - "name": "Clement Hoang", - "url": "https://twitter.com/c8hoang" - }, - "Daniel15": { - "name": "Daniel Lo Nigro", - "url": "https://d.sb/" - }, - "fisherwebdev": { - "name": "Bill Fisher", - "url": "https://twitter.com/fisherwebdev" - }, - "flarnie": { - "name": "Flarnie Marchan", - "url": "https://twitter.com/ProbablyFlarnie" - }, - "gaearon": { - "name": "Dan Abramov", - "url": "https://twitter.com/dan_abramov" - }, - "jaredly": { - "name": "Jared Forsyth", - "url": "https://twitter.com/jaredforsyth" - }, - "jgebhardt": { - "name": "Jonas Gebhardt", - "url": "https://twitter.com/jonasgebhardt" - }, - "jimfb": { - "name": "Jim Sproch", - "url": "http: //www.jimsproch.com" - }, - "jingc": { - "name": "Jing Chen", - "url": "https://twitter.com/jingc" - }, - "josephsavona": { - "name": "Joseph Savona", - "url": "https://twitter.com/en_JS" - }, - "keyanzhang": { - "name": "Keyan Zhang", - "url": "https://twitter.com/keyanzhang" - }, - "kmeht": { - "name": "Kunal Mehta", - "url": "https://github.com/kmeht" - }, - "LoukaN": { - "name": "Lou Husson", - "url": "https://twitter.com/loukan42" - }, - "matthewjohnston4": { - "name": "Matthew Johnston", - "url": "https://github.com/matthewathome" - }, - "nhunzaker": { - "name": "Nathan Hunzaker", - "url": "https://github.com/nhunzaker" - }, - "petehunt": { - "name": "Pete Hunt", - "url": "https://twitter.com/floydophone" - }, - "rachelnabors": { - "name": "Rachel Nabors", - "url": "https://twitter.com/rachelnabors" - }, - "schrockn": { - "name": "Nick Schrock", - "url": "https://twitter.com/schrockn" - }, - "sebmarkbage": { - "name": "Sebastian MarkbΓ₯ge", - "url": "https://twitter.com/sebmarkbage" - }, - "sophiebits": { - "name": "Sophie Alpert", - "url": "https://sophiebits.com/" - }, - "steveluscher": { - "name": "Steven Luscher", - "url": "https://twitter.com/steveluscher" - }, - "tesseralis": { - "name": "Nat Alison", - "url": "https://twitter.com/tesseralis" - }, - "threepointone": { - "name": "Sunil Pai", - "url": "https://twitter.com/threepointone" - }, - "timer": { - "name": "Joe Haddad", - "url": "https://twitter.com/timer150" - }, - "vjeux": { - "name": "Vjeux", - "url": "https://twitter.com/vjeux" - }, - "wincent": { - "name": "Greg Hurrell", - "url": "https://twitter.com/wincent" - }, - "zpao": { - "name": "Paul O’Shannessy", - "url": "https://twitter.com/zpao" - }, - "tomocchino": { - "name": "Tom Occhino", - "url": "https://twitter.com/tomocchino" - } -} diff --git a/beta/src/blogIndex.json b/beta/src/blogIndex.json deleted file mode 100644 index 088a1f82c..000000000 --- a/beta/src/blogIndex.json +++ /dev/null @@ -1,1400 +0,0 @@ -{ - "routes": [ - { - "path": "/blog/2020/08/10/react-v17-rc.md", - "date": "2020-08-10", - "title": "React v17.0 Release Candidate: No New Features", - "author": [ - "gaearon", - "rachelnabors" - ], - "excerpt": "

    Today, we are publishing the first Release Candidate for React 17. It has been two and a half years since the previous major release of React, which is a long time even by our standards! In this blog post, we will describe the role of this major release, what changes you can expect in it, and how you can try this release.

    \n", - "readingTime": "20 min read" - }, - { - "path": "/blog/2020/02/26/react-v16.13.0.md", - "date": "2020-02-26", - "title": "React v16.13.0", - "author": [ - "threepointone" - ], - "excerpt": "

    Today we are releasing React 16.13.0. It contains bugfixes and new deprecation warnings to help prepare for a future major release.

    \n", - "readingTime": "7 min read" - }, - { - "path": "/blog/2019/11/06/building-great-user-experiences-with-concurrent-mode-and-suspense.md", - "date": "2019-11-06", - "title": "Building Great User Experiences with Concurrent Mode and Suspense", - "author": [ - "josephsavona" - ], - "excerpt": "

    At React Conf 2019 we announced an experimental release of React that supports Concurrent Mode and Suspense. In this post we’ll introduce best practices for using them that we’ve identified through the process of building the new facebook.com.

    \n", - "readingTime": "17 min read" - }, - { - "path": "/blog/2019/10/22/react-release-channels.md", - "date": "2019-10-22", - "title": "Preparing for the Future with React Prereleases", - "author": [ - "acdlite" - ], - "excerpt": "

    To share upcoming changes with our partners in the React ecosystem, we’re establishing official prerelease channels. We hope this process will help us make changes to React with confidence, and give developers the opportunity to try out experimental features.

    \n", - "readingTime": "7 min read" - }, - { - "path": "/blog/2019/08/15/new-react-devtools.md", - "date": "2019-08-15", - "title": "Introducing the New React DevTools", - "author": [ - "bvaughn" - ], - "excerpt": "

    We are excited to announce a new release of the React Developer Tools, available today in Chrome, Firefox, and (Chromium) Edge!

    \n", - "readingTime": "2 min read" - }, - { - "path": "/blog/2019/08/08/react-v16.9.0.md", - "date": "2019-08-08", - "title": "React v16.9.0 and the Roadmap Update", - "author": [ - "gaearon", - "bvaughn" - ], - "excerpt": "

    Today we are releasing React 16.9. It contains several new features, bugfixes, and new deprecation warnings to help prepare for a future major release.

    \n", - "readingTime": "11 min read" - }, - { - "path": "/blog/2019/02/23/is-react-translated-yet.md", - "date": "2019-02-23", - "title": "Is React Translated Yet? Β‘SΓ­! Sim! はい!", - "author": [ - "tesseralis" - ], - "excerpt": "

    We’re excited to announce an ongoing effort to maintain official translations of the React documentation website into different languages. Thanks to the dedicated efforts of React community members from around the world, React is now being translated into over 30 languages! You can find them on the new Languages page.

    \n", - "readingTime": "7 min read" - }, - { - "path": "/blog/2019/02/06/react-v16.8.0.md", - "date": "2019-02-06", - "title": "React v16.8: The One With Hooks", - "author": [ - "gaearon" - ], - "excerpt": "

    With React 16.8, React Hooks are available in a stable release!

    \n", - "readingTime": "7 min read" - }, - { - "path": "/blog/2018/12/19/react-v-16-7.md", - "date": "2018-12-19", - "title": "React v16.7: No, This Is Not the One With Hooks", - "author": [ - "acdlite" - ], - "excerpt": "

    Our latest release includes an important performance bugfix for React.lazy. Although there are no API changes, we’re releasing it as a minor instead of a patch.

    \n", - "readingTime": "3 min read" - }, - { - "path": "/blog/2018/11/27/react-16-roadmap.md", - "date": "2018-11-27", - "title": "React 16.x Roadmap", - "author": [ - "gaearon" - ], - "excerpt": "

    You might have heard about features like β€œHooks”, β€œSuspense”, and β€œConcurrent Rendering” in the previous blog posts and talks. In this post, we’ll look at how they fit together and the expected timeline for their availability in a stable release of React.

    \n", - "readingTime": "14 min read" - }, - { - "path": "/blog/2018/11/13/react-conf-recap.md", - "date": "2018-11-13", - "title": "React Conf recap: Hooks, Suspense, and Concurrent Rendering", - "author": [ - "tomocchino" - ], - "excerpt": "

    This year’s React Conf took place on October 25 and 26 in Henderson, Nevada, where more than 600 attendees gathered to discuss the latest in UI engineering.

    \n", - "readingTime": "2 min read" - }, - { - "path": "/blog/2018/10/23/react-v-16-6.md", - "date": "2018-10-23", - "title": "React v16.6.0: lazy, memo and contextType", - "author": [ - "sebmarkbage" - ], - "excerpt": "

    Today we’re releasing React 16.6 with a few new convenient features. A form of PureComponent/shouldComponentUpdate for function components, a way to do code splitting using Suspense and an easier way to consume Context from class components.

    \n", - "readingTime": "5 min read" - }, - { - "path": "/blog/2018/10/01/create-react-app-v2.md", - "date": "2018-10-01", - "title": "Create React App 2.0: BabelΒ 7, Sass, and More", - "author": [ - "timer", - "gaearon" - ], - "excerpt": "

    Create React App 2.0 has been released today, and it brings a year’s worth of improvements in a single dependency update.

    \n", - "readingTime": "6 min read" - }, - { - "path": "/blog/2018/09/10/introducing-the-react-profiler.md", - "date": "2018-09-10", - "title": "Introducing the React Profiler", - "author": [ - "bvaughn" - ], - "excerpt": "

    React 16.5 adds support for a new DevTools profiler plugin.

    \n", - "readingTime": "8 min read" - }, - { - "path": "/blog/2018/08/01/react-v-16-4-2.md", - "date": "2018-08-01", - "title": "React v16.4.2: Server-side vulnerability fix", - "author": [ - "gaearon" - ], - "excerpt": "

    We discovered a minor vulnerability that might affect some apps using ReactDOMServer. We are releasing a patch version for every affected React minor release so that you can upgrade with no friction. Read on for more details.

    \n", - "readingTime": "4 min read" - }, - { - "path": "/blog/2018/06/07/you-probably-dont-need-derived-state.md", - "date": "2018-06-07", - "title": "You Probably Don't Need Derived State", - "author": [ - "bvaughn" - ], - "excerpt": "

    React 16.4 included a bugfix for getDerivedStateFromProps which caused some existing bugs in React components to reproduce more consistently. If this release exposed a case where your application was using an anti-pattern and didn’t work properly after the fix, we’re sorry for the churn. In this post, we will explain some common anti-patterns with derived state and our preferred alternatives.

    \n", - "readingTime": "14 min read" - }, - { - "path": "/blog/2018/05/23/react-v-16-4.md", - "date": "2018-05-23", - "title": "React v16.4.0: Pointer Events", - "author": [ - "acdlite" - ], - "excerpt": "

    The latest minor release adds support for an oft-requested feature: pointer events!

    \n", - "readingTime": "5 min read" - }, - { - "path": "/blog/2018/03/29/react-v-16-3.md", - "date": "2018-03-29", - "title": "React v16.3.0: New lifecycles and context API", - "author": [ - "bvaughn" - ], - "excerpt": "

    A few days ago, we wrote a post about upcoming changes to our legacy lifecycle methods, including gradual migration strategies. In React 16.3.0, we are adding a few new lifecycle methods to assist with that migration. We are also introducing new APIs for long requested features: an official context API, a ref forwarding API, and an ergonomic ref API.

    \n", - "readingTime": "6 min read" - }, - { - "path": "/blog/2018/03/27/update-on-async-rendering.md", - "date": "2018-03-27", - "title": "Update on Async Rendering", - "author": [ - "bvaughn" - ], - "excerpt": "

    For over a year, the React team has been working to implement asynchronous rendering. Last month during his talk at JSConf Iceland, Dan unveiled some of the exciting new possibilities async rendering unlocks. Now we’d like to share with you some of the lessons we’ve learned while working on these features, and some recipes to help prepare your components for async rendering when it launches.

    \n", - "readingTime": "12 min read" - }, - { - "path": "/blog/2018/03/01/sneak-peek-beyond-react-16.md", - "date": "2018-03-01", - "title": "Sneak Peek: Beyond React 16", - "author": [ - "sophiebits" - ], - "excerpt": "

    Dan Abramov from our team just spoke at JSConf Iceland 2018 with a preview of some new features we’ve been working on in React. The talk opens with a question: β€œWith vast differences in computing power and network speed, how do we deliver the best user experience for everyone?”

    \n", - "readingTime": "2 min read" - }, - { - "path": "/blog/2017/12/15/improving-the-repository-infrastructure.md", - "date": "2017-12-15", - "title": "Behind the Scenes: Improving the Repository Infrastructure", - "author": [ - "gaearon", - "bvaughn" - ], - "excerpt": "

    As we worked on React 16, we revamped the folder structure and much of the build tooling in the React repository. Among other things, we introduced projects such as Rollup, Prettier, and Google Closure Compiler into our workflow. People often ask us questions about how we use those tools. In this post, we would like to share some of the changes that we’ve made to our build and test infrastructure in 2017, and what motivated them.

    \n", - "readingTime": "30 min read" - }, - { - "path": "/blog/2017/12/07/introducing-the-react-rfc-process.md", - "date": "2017-12-07", - "title": "Introducing the React RFC Process", - "author": [ - "acdlite" - ], - "excerpt": "

    We’re adopting an RFC (β€œrequest for comments”) process for contributing ideas to React.

    \n", - "readingTime": "2 min read" - }, - { - "path": "/blog/2017/11/28/react-v16.2.0-fragment-support.md", - "date": "2017-11-28", - "title": "React v16.2.0: Improved Support for Fragments", - "author": [ - "clemmy" - ], - "excerpt": "

    React 16.2 is now available! The biggest addition is improved support for returning multiple children from a component’s render method. We call this feature fragments:

    \n", - "readingTime": "8 min read" - }, - { - "path": "/blog/2017/09/26/react-v16.0.md", - "date": "2017-09-26", - "title": "React v16.0", - "author": [ - "acdlite" - ], - "excerpt": "

    We’re excited to announce the release of React v16.0! Among the changes are some long-standing feature requests, including fragments, error boundaries, portals, support for custom DOM attributes, improved server-side rendering, and reduced file size.

    \n", - "readingTime": "11 min read" - }, - { - "path": "/blog/2017/09/25/react-v15.6.2.md", - "date": "2017-09-25", - "title": "React v15.6.2", - "author": [ - "nhunzaker" - ], - "excerpt": "

    Today we’re sending out React 15.6.2. In 15.6.1, we shipped a few fixes for change events and inputs that had some unintended consequences. Those regressions have been ironed out, and we’ve also included a few more fixes to improve the stability of React across all browsers.

    \n", - "readingTime": "3 min read" - }, - { - "path": "/blog/2017/09/08/dom-attributes-in-react-16.md", - "date": "2017-09-08", - "title": "DOM Attributes in React 16", - "author": [ - "gaearon" - ], - "excerpt": "

    In the past, React used to ignore unknown DOM attributes. If you wrote JSX with an attribute that React doesn’t recognize, React would just skip it. For example, this:

    \n", - "readingTime": "6 min read" - }, - { - "path": "/blog/2017/07/26/error-handling-in-react-16.md", - "date": "2017-07-26", - "title": "Error Handling in React 16", - "author": [ - "gaearon" - ], - "excerpt": "

    As React 16 release is getting closer, we would like to announce a few changes to how React handles JavaScript errors inside components. These changes are included in React 16 beta versions, and will be a part of React 16.

    \n", - "readingTime": "5 min read" - }, - { - "path": "/blog/2017/06/13/react-v15.6.0.md", - "date": "2017-06-13", - "title": "React v15.6.0", - "author": [ - "flarnie" - ], - "excerpt": "

    Today we are releasing React 15.6.0. As we prepare for React 16.0, we have been fixing and cleaning up many things. This release continues to pave the way.

    \n", - "readingTime": "4 min read" - }, - { - "path": "/blog/2017/05/18/whats-new-in-create-react-app.md", - "date": "2017-05-18", - "title": "What's New in Create React App", - "author": [ - "gaearon" - ], - "excerpt": "

    Less than a year ago, we introduced Create React App as an officially supported way to create apps with zero configuration. The project has since enjoyed tremendous growth, with over 950 commits by more than 250 contributors.

    \n", - "readingTime": "6 min read" - }, - { - "path": "/blog/2017/04/07/react-v15.5.0.md", - "date": "2017-04-07", - "title": "React v15.5.0", - "author": [ - "acdlite" - ], - "excerpt": "

    It’s been exactly one year since the last breaking change to React. Our next major release, React 16, will include some exciting improvements, including a complete rewrite of React’s internals. We take stability seriously, and are committed to bringing those improvements to all of our users with minimal effort.

    \n", - "readingTime": "7 min read" - }, - { - "path": "/blog/2016/11/16/react-v15.4.0.md", - "date": "2016-11-16", - "title": "React v15.4.0", - "author": [ - "gaearon" - ], - "excerpt": "

    Today we are releasing React 15.4.0.

    \n", - "readingTime": "6 min read" - }, - { - "path": "/blog/2016/09/28/our-first-50000-stars.md", - "date": "2016-09-28", - "title": "Our First 50,000 Stars", - "author": [ - "vjeux" - ], - "excerpt": "

    Just three and a half years ago we open sourced a little JavaScript library called React. The journey since that day has been incredibly exciting.

    \n", - "readingTime": "10 min read" - }, - { - "path": "/blog/2016/08/05/relay-state-of-the-state.md", - "date": "2016-08-05", - "title": "Relay: State of the State", - "author": [ - "josephsavona" - ], - "excerpt": "

    This month marks a year since we released Relay and we’d like to share an update on the project and what’s next.

    \n", - "readingTime": "8 min read" - }, - { - "path": "/blog/2016/07/22/create-apps-with-no-configuration.md", - "date": "2016-07-22", - "title": "Create Apps with No Configuration", - "author": [ - "gaearon" - ], - "excerpt": "

    Create React App is a new officially supported way to create single-page React applications. It offers a modern build setup with no configuration.

    \n", - "readingTime": "7 min read" - }, - { - "path": "/blog/2016/07/13/mixins-considered-harmful.md", - "date": "2016-07-13", - "title": "Mixins Considered Harmful", - "author": [ - "gaearon" - ], - "excerpt": "

    β€œHow do I share the code between several components?” is one of the first questions that people ask when they learn React. Our answer has always been to use component composition for code reuse. You can define a component and use it in several other components.

    \n", - "readingTime": "20 min read" - }, - { - "path": "/blog/2016/07/11/introducing-reacts-error-code-system.md", - "date": "2016-07-11", - "title": "Introducing React's Error Code System", - "author": [ - "keyanzhang" - ], - "excerpt": "

    Building a better developer experience has been one of the things that React deeply cares about, and a crucial part of it is to detect anti-patterns/potential errors early and provide helpful error messages when things (may) go wrong. However, most of these only exist in development mode; in production, we avoid having extra expensive assertions and sending down full error messages in order to reduce the number of bytes sent over the wire.

    \n", - "readingTime": "2 min read" - }, - { - "path": "/blog/2016/04/08/react-v15.0.1.md", - "date": "2016-04-08", - "title": "React v15.0.1", - "author": [ - "zpao" - ], - "excerpt": "

    Yesterday afternoon we shipped v15.0.0 and quickly got some feedback about a couple of issues. We apologize for these problems and we’ve been working since then to make sure we get fixes into your hands as quickly as possible.

    \n", - "readingTime": "3 min read" - }, - { - "path": "/blog/2016/04/07/react-v15.md", - "date": "2016-04-07", - "title": "React v15.0", - "author": [ - "gaearon" - ], - "excerpt": "

    We would like to thank the React community for reporting issues and regressions in the release candidates on our issue tracker. Over the last few weeks we fixed those issues, and now, after two release candidates, we are excited to finally release the stable version of React 15.

    \n", - "readingTime": "15 min read" - }, - { - "path": "/blog/2016/03/29/react-v0.14.8.md", - "date": "2016-03-29", - "title": "React v0.14.8", - "author": [ - "gaearon" - ], - "excerpt": "

    We have already released two release candidates for React 15, and the final version is coming soon.

    \n", - "readingTime": "1 min read" - }, - { - "path": "/blog/2016/03/16/react-v15-rc2.md", - "date": "2016-03-16", - "title": "React v15.0 Release Candidate 2", - "author": [ - "zpao" - ], - "excerpt": "

    Today we’re releasing a second release candidate for version 15. Primarily this is to address 2 issues, but we also picked up a few small changes from new contributors, including some improvements to some of our new warnings.

    \n", - "readingTime": "3 min read" - }, - { - "path": "/blog/2016/03/07/react-v15-rc1.md", - "date": "2016-03-07", - "title": "React v15.0 Release Candidate", - "author": [ - "zpao" - ], - "excerpt": "

    Sorry for the small delay in releasing this. As we said, we’ve been busy binge-watching House of Cards. That scene in the last episode where Francis and Claire Underwood β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆ. WOW!

    \n", - "readingTime": "8 min read" - }, - { - "path": "/blog/2016/02/19/new-versioning-scheme.md", - "date": "2016-02-19", - "title": "New Versioning Scheme", - "author": [ - "sebmarkbage" - ], - "excerpt": "

    Today we’re announcing that we’re switching to major revisions for React. The current version is 0.14.7. The next release will be: 15.0.0

    \n", - "readingTime": "4 min read" - }, - { - "path": "/blog/2016/01/12/discontinuing-ie8-support.md", - "date": "2016-01-12", - "title": "Discontinuing IEΒ 8 Support in ReactΒ DOM", - "author": [ - "sophiebits" - ], - "excerpt": "

    Since its 2013 release, React has supported all popular browsers, including Internet ExplorerΒ 8 and above. We handle normalizing many quirks present in old browser versions, including event system differences, so that your app code doesn’t have to worry about most browser bugs.

    \n", - "readingTime": "1 min read" - }, - { - "path": "/blog/2016/01/08/A-implies-B-does-not-imply-B-implies-A.md", - "date": "2016-01-08", - "title": "(A => B) !=> (B => A)", - "author": [ - "jimfb" - ], - "excerpt": "

    The documentation for componentWillReceiveProps states that componentWillReceiveProps will be invoked when the props change as the result of a rerender. Some people assume this means β€œif componentWillReceiveProps is called, then the props must have changed”, but that conclusion is logically incorrect.

    \n", - "readingTime": "4 min read" - }, - { - "path": "/blog/2015/12/29/react-v0.14.4.md", - "date": "2015-12-29", - "title": "React v0.14.4", - "author": [ - "sophiebits" - ], - "excerpt": "

    Happy December! We have a minor point release today. It has just a few small bug fixes.

    \n", - "readingTime": "1 min read" - }, - { - "path": "/blog/2015/12/18/react-components-elements-and-instances.md", - "date": "2015-12-18", - "title": "React Components, Elements, and Instances", - "author": [ - "gaearon" - ], - "excerpt": "

    The difference between components, their instances, and elements confuses many React beginners. Why are there three different terms to refer to something that is painted on screen?

    \n", - "readingTime": "11 min read" - }, - { - "path": "/blog/2015/12/16/ismounted-antipattern.md", - "date": "2015-12-16", - "title": "isMounted is an Antipattern", - "author": [ - "jimfb" - ], - "excerpt": "

    As we move closer to officially deprecating isMounted, it’s worth understanding why the function is an antipattern, and how to write code without the isMounted function.

    \n", - "readingTime": "3 min read" - }, - { - "path": "/blog/2015/12/04/react-js-conf-2016-diversity-scholarship.md", - "date": "2015-12-04", - "title": "React.js Conf 2016 Diversity Scholarship", - "author": [ - "zpao" - ], - "excerpt": "

    I am thrilled to announced that we will be organizing another diversity scholarship program for the upcoming React.js Conf! The tech industry is suffering from a lack of diversity, but it’s important to us that we have a thriving community that is made up of people with a variety of experiences and viewpoints.

    \n", - "readingTime": "4 min read" - }, - { - "path": "/blog/2015/11/18/react-v0.14.3.md", - "date": "2015-11-18", - "title": "React v0.14.3", - "author": [ - "zpao" - ], - "excerpt": "

    It’s time for another installment of React patch releases! We didn’t break anything in v0.14.2 but we do have a couple of other bugs we’re fixing. The biggest change in this release is actually an addition of a new built file. We heard from a number of people that they still need the ability to use React to render to a string on the client. While the use cases are not common and there are other ways to achieve this, we decided that it’s still valuable to support. So we’re now building react-dom-server.js, which will be shipped to Bower and in the dist/ directory of the react-dom package on npm. This file works the same way as react-dom.js and therefore requires that the primary React build has already been included on the page.

    \n", - "readingTime": "2 min read" - }, - { - "path": "/blog/2015/11/02/react-v0.14.2.md", - "date": "2015-11-02", - "title": "React v0.14.2", - "author": [ - "zpao" - ], - "excerpt": "

    We have a quick update following the release of 0.14.1 last week. It turns out we broke a couple things in the development build of React when using Internet Explorer. Luckily it was only the development build, so your production applications were unaffected. This release is mostly to address those issues. There is one notable change if consuming React from npm. For the react-dom package, we moved react from a regular dependency to a peer dependency. This will impact very few people as these two are typically installed together at the top level, but it will fix some issues with dependencies of installed components also using react as a peer dependency.

    \n", - "readingTime": "2 min read" - }, - { - "path": "/blog/2015/10/28/react-v0.14.1.md", - "date": "2015-10-28", - "title": "React v0.14.1", - "author": [ - "zpao" - ], - "excerpt": "

    After a couple weeks of having more people use v0.14, we’re ready to ship a patch release addressing a few issues. Thanks to everybody who has reported issues and written patches!

    \n", - "readingTime": "2 min read" - }, - { - "path": "/blog/2015/10/19/reactiflux-is-moving-to-discord.md", - "date": "2015-10-19", - "title": "Reactiflux is moving to Discord", - "author": [ - "benigeri" - ], - "excerpt": "

    TL;DR: Slack decided that Reactiflux had too many members and disabled new invites. Reactiflux is moving to Discord. Join us: http://join.reactiflux.com

    \n", - "readingTime": "5 min read" - }, - { - "path": "/blog/2015/10/07/react-v0.14.md", - "date": "2015-10-07", - "title": "React v0.14", - "author": [ - "sophiebits" - ], - "excerpt": "

    We’re happy to announce the release of React 0.14 today! This release has a few major changes, primarily designed to simplify the code you write every day and to better support environments like React Native.

    \n", - "readingTime": "12 min read" - }, - { - "path": "/blog/2015/10/01/react-render-and-top-level-api.md", - "date": "2015-10-01", - "title": "ReactDOM.render and the Top Level React API", - "author": [ - "jimfb", - "sebmarkbage" - ], - "excerpt": "

    When you’re in React’s world you are just building components that fit into other components. Everything is a component. Unfortunately not everything around you is built using React. At the root of your tree you still have to write some plumbing code to connect the outer world into React.

    \n", - "readingTime": "4 min read" - }, - { - "path": "/blog/2015/09/14/community-roundup-27.md", - "date": "2015-09-14", - "title": "Community Round-up #27 – Relay Edition", - "author": [ - "steveluscher" - ], - "excerpt": "

    In the weeks following the open-source release of the Relay technical preview, the community has been abuzz with activity. We are honored to have been able to enjoy a steady stream of ideas and contributions from such a talented group of individuals. Let’s take a look at some of the things we’ve achieved, together!

    \n", - "readingTime": "4 min read" - }, - { - "path": "/blog/2015/09/10/react-v0.14-rc1.md", - "date": "2015-09-10", - "title": "React v0.14 Release Candidate", - "author": [ - "sophiebits" - ], - "excerpt": "

    We’re happy to announce our first release candidate for React 0.14! We gave you a sneak peek in July at the upcoming changes but we’ve now stabilized the release more and we’d love for you to try it out before we release the final version.

    \n", - "readingTime": "11 min read" - }, - { - "path": "/blog/2015/09/02/new-react-developer-tools.md", - "date": "2015-09-02", - "title": "New React Developer Tools", - "author": [ - "sophiebits" - ], - "excerpt": "

    A month ago, we posted a beta of the new React developer tools. Today, we’re releasing the first stable version of the new devtools. We’re calling it version 0.14, but it’s a full rewrite so we think of it more like a 2.0 release.

    \n", - "readingTime": "2 min read" - }, - { - "path": "/blog/2015/08/13/reacteurope-roundup.md", - "date": "2015-08-13", - "title": "ReactEurope Round-up", - "author": [ - "matthewjohnston4" - ], - "excerpt": "

    Last month, the first React.js European conference took place in the city of Paris, at ReactEurope. Attendees were treated to a range of talks covering React, React Native, Flux, Relay, and GraphQL. Big thanks to everyone involved with organizing the conference, to all the attendees, and everyone who gave their time to speak - it wouldn’t have been possible without the help and support of the React community.

    \n", - "readingTime": "5 min read" - }, - { - "path": "/blog/2015/08/11/relay-technical-preview.md", - "date": "2015-08-11", - "title": "Relay Technical Preview", - "author": [ - "josephsavona" - ], - "excerpt": "

    Relay

    \n", - "readingTime": "3 min read" - }, - { - "path": "/blog/2015/08/03/new-react-devtools-beta.md", - "date": "2015-08-03", - "title": "New React Devtools Beta", - "author": [ - "jaredly" - ], - "excerpt": "

    We’ve made an entirely new version of the devtools, and we want you to try it

    \n", - "readingTime": "3 min read" - }, - { - "path": "/blog/2015/07/03/react-v0.14-beta-1.md", - "date": "2015-07-03", - "title": "React v0.14 Beta 1", - "author": [ - "sophiebits" - ], - "excerpt": "

    This week, many people in the React community are at ReactEurope in the beautiful (and very warm) city of Paris, the second React conference that’s been held to date. At our last conference, we released the first beta of React 0.13, and we figured we’d do the same today with our first beta of React 0.14, giving you something to play with if you’re not at the conference or you’re looking for something to do on the way home.

    \n", - "readingTime": "5 min read" - }, - { - "path": "/blog/2015/06/12/deprecating-jstransform-and-react-tools.md", - "date": "2015-06-12", - "title": "Deprecating JSTransform and react-tools", - "author": [ - "zpao" - ], - "excerpt": "

    Today we’re announcing the deprecation of react-tools and JSTransform.

    \n", - "readingTime": "3 min read" - }, - { - "path": "/blog/2015/05/22/react-native-release-process.md", - "date": "2015-05-22", - "title": "React Native Release Process", - "author": [ - "vjeux" - ], - "excerpt": "

    The React Native release process have been a bit chaotic since we open sourced. It was unclear when new code was released, there was no changelog, we bumped the minor and patch version inconsistently and we often had to submit updates right after a release to fix a bad bug. In order to move fast with stable infra, we are introducing a real release process with a two-week release schedule.

    \n", - "readingTime": "2 min read" - }, - { - "path": "/blog/2015/05/08/react-v0.13.3.md", - "date": "2015-05-08", - "title": "React v0.13.3", - "author": [ - "zpao" - ], - "excerpt": "

    Today we’re sharing another patch release in the v0.13 branch. There are only a few small changes, with a couple to address some issues that arose around that undocumented feature so many of you are already using: context. We also improved developer ergonomics just a little bit, making some warnings better.

    \n", - "readingTime": "1 min read" - }, - { - "path": "/blog/2015/05/01/graphql-introduction.md", - "date": "2015-05-01", - "title": "GraphQL Introduction", - "author": [ - "schrockn" - ], - "excerpt": "

    At the React.js conference in late January 2015, we revealed our next major technology in the React family: Relay.

    \n", - "readingTime": "11 min read" - }, - { - "path": "/blog/2015/04/18/react-v0.13.2.md", - "date": "2015-04-18", - "title": "React v0.13.2", - "author": [ - "zpao" - ], - "excerpt": "

    Yesterday the React Native team shipped v0.4. Those of us working on the web team just a few feet away couldn’t just be shown up like that so we’re shipping v0.13.2 today as well! This is a bug fix release to address a few things while we continue to work towards v0.14.

    \n", - "readingTime": "2 min read" - }, - { - "path": "/blog/2015/04/17/react-native-v0.4.md", - "date": "2015-04-17", - "title": "React Native v0.4", - "author": [ - "vjeux" - ], - "excerpt": "

    It’s been three weeks since we open sourced React Native and there’s been some insane amount of activity already: over 12.5k stars, 1000 commits, 500 issues, 380 pull requests, and 100 contributors, plus 35 plugins and 1 app in the app store! We were expecting some buzz around the project but this is way beyond anything we imagined. Thank you!

    \n", - "readingTime": "3 min read" - }, - { - "path": "/blog/2015/03/30/community-roundup-26.md", - "date": "2015-03-30", - "title": "Community Round-up #26", - "author": [ - "vjeux" - ], - "excerpt": "

    We open sourced React Native last week and the community reception blew away all our expectations! So many of you tried it, made cool stuff with it, raised many issues and even submitted pull requests to fix them! The entire team wants to say thank you!

    \n", - "readingTime": "4 min read" - }, - { - "path": "/blog/2015/03/26/introducing-react-native.md", - "date": "2015-03-26", - "title": "Introducing React Native", - "author": [ - "sophiebits" - ], - "excerpt": "

    In January at React.js Conf, we announced React Native, a new framework for building native apps using React. We’re happy to announce that we’re open-sourcing React Native and you can start building your apps with it today.

    \n", - "readingTime": "2 min read" - }, - { - "path": "/blog/2015/03/19/building-the-facebook-news-feed-with-relay.md", - "date": "2015-03-19", - "title": "Building The Facebook News Feed With Relay", - "author": [ - "josephsavona" - ], - "excerpt": "

    At React.js Conf in January we gave a preview of Relay, a new framework for building data-driven applications in React. In this post, we’ll describe the process of creating a Relay application. This post assumes some familiarity with the concepts of Relay and GraphQL, so if you haven’t already we recommend reading our introductory blog post or watching the conference talk.

    \n", - "readingTime": "7 min read" - }, - { - "path": "/blog/2015/03/16/react-v0.13.1.md", - "date": "2015-03-16", - "title": "React v0.13.1", - "author": [ - "zpao" - ], - "excerpt": "

    It’s been less than a week since we shipped v0.13.0 but it’s time to do another quick release. We just released v0.13.1 which contains bugfixes for a number of small issues.

    \n", - "readingTime": "2 min read" - }, - { - "path": "/blog/2015/03/10/react-v0.13.md", - "date": "2015-03-10", - "title": "React v0.13", - "author": [ - "sophiebits" - ], - "excerpt": "

    Today, we’re happy to release React v0.13!

    \n", - "readingTime": "5 min read" - }, - { - "path": "/blog/2015/03/04/community-roundup-25.md", - "date": "2015-03-04", - "title": "Community Round-up #25", - "author": [ - "matthewjohnston4" - ], - "excerpt": "

    React 101

    \n", - "readingTime": "3 min read" - }, - { - "path": "/blog/2015/03/03/react-v0.13-rc2.md", - "date": "2015-03-03", - "title": "React v0.13 RC2", - "author": [ - "sebmarkbage" - ], - "excerpt": "

    Thanks to everybody who has already been testing the release candidate. We’ve received some good feedback and as a result we’re going to do a second release candidate. The changes are minimal. We haven’t changed the behavior of any APIs we exposed in the previous release candidate. Here’s a summary of the changes:

    \n", - "readingTime": "3 min read" - }, - { - "path": "/blog/2015/02/24/streamlining-react-elements.md", - "date": "2015-02-24", - "title": "Streamlining React Elements", - "author": [ - "sebmarkbage" - ], - "excerpt": "

    React v0.13 is right around the corner and so we wanted to discuss some upcoming changes to ReactElement. In particular, we added several warnings to some esoteric use cases of ReactElement. There are no runtime behavior changes for ReactElement - we’re adding these warnings in the hope that we can change some behavior in v0.14 if the changes are valuable to the community.

    \n", - "readingTime": "10 min read" - }, - { - "path": "/blog/2015/02/24/react-v0.13-rc1.md", - "date": "2015-02-24", - "title": "React v0.13 RC", - "author": [ - "zpao" - ], - "excerpt": "

    Over the weekend we pushed out our first (and hopefully only) release candidate for React v0.13!

    \n", - "readingTime": "4 min read" - }, - { - "path": "/blog/2015/02/20/introducing-relay-and-graphql.md", - "date": "2015-02-20", - "title": "Introducing Relay and GraphQL", - "author": [ - "wincent" - ], - "excerpt": "

    Data fetching for React applications

    \n", - "readingTime": "7 min read" - }, - { - "path": "/blog/2015/02/18/react-conf-roundup-2015.md", - "date": "2015-02-18", - "title": "React.js Conf Round-up 2015", - "author": [ - "steveluscher" - ], - "excerpt": "

    It was a privilege to welcome the React community to Facebook HQ on January 28–29 for the first-ever React.js Conf, and a pleasure to be able to unveil three new technologies that we’ve been using internally at Facebook for some time: GraphQL, Relay, and React Native.

    \n", - "readingTime": "8 min read" - }, - { - "path": "/blog/2015/01/27/react-v0.13.0-beta-1.md", - "date": "2015-01-27", - "title": "React v0.13.0 Beta 1", - "author": [ - "sebmarkbage" - ], - "excerpt": "

    React 0.13 has a lot of nice features but there is one particular feature that I’m really excited about. I couldn’t wait for React.js Conf to start tomorrow morning.

    \n", - "readingTime": "5 min read" - }, - { - "path": "/blog/2014/12/19/react-js-conf-diversity-scholarship.md", - "date": "2014-12-19", - "title": "React.js Conf Diversity Scholarship", - "author": [ - "zpao" - ], - "excerpt": "

    Today I’m really happy to announce the React.js Conf Diversity Scholarship! We believe that a diverse set of viewpoints and opinions is really important to build a thriving community. In an ideal world, every part of the tech community would be made up of people from all walks of life. However the reality is that we must be proactive and make an effort to make sure everybody has a voice. As conference organizers we worked closely with the Diversity Team here at Facebook to set aside 10 tickets and provide a scholarship. 10 tickets may not be many in the grand scheme but we really believe that this will have a positive impact on the discussions we have at the conference.

    \n", - "readingTime": "3 min read" - }, - { - "path": "/blog/2014/12/18/react-v0.12.2.md", - "date": "2014-12-18", - "title": "React v0.12.2", - "author": [ - "zpao" - ], - "excerpt": "

    We just shipped React v0.12.2, bringing the 0.12 branch up to date with a few small fixes that landed in master over the past 2 months.

    \n", - "readingTime": "2 min read" - }, - { - "path": "/blog/2014/11/25/community-roundup-24.md", - "date": "2014-11-25", - "title": "Community Round-up #24", - "author": [ - "steveluscher" - ], - "excerpt": "

    Keep it Simple

    \n", - "readingTime": "5 min read" - }, - { - "path": "/blog/2014/11/24/react-js-conf-updates.md", - "date": "2014-11-24", - "title": "React.js Conf Updates", - "author": [ - "vjeux" - ], - "excerpt": "

    Yesterday was the React.js Conf call for presenters submission deadline. We were

    \n", - "readingTime": "2 min read" - }, - { - "path": "/blog/2014/10/28/react-v0.12.md", - "date": "2014-10-28", - "title": "React v0.12", - "author": [ - "zpao" - ], - "excerpt": "

    We’re happy to announce the availability of React v0.12! After over a week of baking as the release candidate, we uncovered and fixed a few small issues. Thanks to all of you who upgraded and gave us feedback!

    \n", - "readingTime": "6 min read" - }, - { - "path": "/blog/2014/10/27/react-js-conf.md", - "date": "2014-10-27", - "title": "React.js Conf", - "author": [ - "vjeux" - ], - "excerpt": "

    Every few weeks someone asks us when we are going to organize a conference for React. Our answer has always been β€œsome day”. In the mean time, people have been talking about React at other JavaScript conferences around the world. But now the time has finally come for us to have a conference of our own.

    \n", - "readingTime": "1 min read" - }, - { - "path": "/blog/2014/10/17/community-roundup-23.md", - "date": "2014-10-17", - "title": "Community Round-up #23", - "author": [ - "LoukaN" - ], - "excerpt": "

    This round-up is a special edition on Flux. If you expect to see diagrams showing arrows that all point in the same direction, you won’t be disappointed!

    \n", - "readingTime": "6 min read" - }, - { - "path": "/blog/2014/10/16/react-v0.12-rc1.md", - "date": "2014-10-16", - "title": "React v0.12 RC", - "author": [ - "sebmarkbage" - ], - "excerpt": "

    We are finally ready to share the work we’ve been doing over the past couple months. A lot has gone into this and we want to make sure we iron out any potential issues before we make this final. So, we’re shipping a Release Candidate for React v0.12 today. If you get a chance, please give it a try and report any issues you find! A full changelog will accompany the final release but we’ve highlighted the interesting and breaking changes below.

    \n", - "readingTime": "6 min read" - }, - { - "path": "/blog/2014/10/14/introducing-react-elements.md", - "date": "2014-10-14", - "title": "Introducing React Elements", - "author": [ - "sebmarkbage" - ], - "excerpt": "

    The upcoming React 0.12 tweaks some APIs to get us close to the final 1.0 API. This release is all about setting us up for making the ReactElement type really FAST, jest unit testing easier, making classes simpler (in preparation for ES6 classes) and better integration with third-party languages!

    \n", - "readingTime": "7 min read" - }, - { - "path": "/blog/2014/09/24/testing-flux-applications.md", - "date": "2014-09-24", - "title": "Testing Flux Applications", - "author": [ - "fisherwebdev" - ], - "excerpt": "

    A more up-to-date version of this post is available as part of the Flux documentation.

    \n", - "readingTime": "8 min read" - }, - { - "path": "/blog/2014/09/16/react-v0.11.2.md", - "date": "2014-09-16", - "title": "React v0.11.2", - "author": [ - "zpao" - ], - "excerpt": "

    Today we’re releasing React v0.11.2 to add a few small features.

    \n", - "readingTime": "2 min read" - }, - { - "path": "/blog/2014/09/12/community-round-up-22.md", - "date": "2014-09-12", - "title": "Community Round-up #22", - "author": [ - "LoukaN" - ], - "excerpt": "

    This has been an exciting summer as four big companies: Yahoo, Mozilla, Airbnb and Reddit announced that they were using React!

    \n", - "readingTime": "4 min read" - }, - { - "path": "/blog/2014/09/03/introducing-the-jsx-specification.md", - "date": "2014-09-03", - "title": "Introducing the JSX Specification", - "author": [ - "sebmarkbage" - ], - "excerpt": "

    At Facebook we’ve been using JSX for a long time. We originally introduced it to the world last year alongside React, but we actually used it in another form before that to create native DOM nodes. We’ve also seen some similar efforts grow out of our work in order to be used with other libraries and in interesting ways. At this point React JSX is just one of many implementations.

    \n", - "readingTime": "1 min read" - }, - { - "path": "/blog/2014/08/03/community-roundup-21.md", - "date": "2014-08-03", - "title": "Community Round-up #21", - "author": [ - "LoukaN" - ], - "excerpt": "

    React Router

    \n", - "readingTime": "3 min read" - }, - { - "path": "/blog/2014/07/30/flux-actions-and-the-dispatcher.md", - "date": "2014-07-30", - "title": "Flux: Actions and the Dispatcher", - "author": [ - "fisherwebdev" - ], - "excerpt": "

    Flux is the application architecture Facebook uses to build JavaScript applications. It’s based on a unidirectional data flow. We’ve built everything from small widgets to huge applications with Flux, and it’s handled everything we’ve thrown at it. Because we’ve found it to be a great way to structure our code, we’re excited to share it with the open source community. Jing Chen presented Flux at the F8 conference, and since that time we’ve seen a lot of interest in it. We’ve also published an overview of Flux and a TodoMVC example, with an accompanying tutorial.

    \n", - "readingTime": "5 min read" - }, - { - "path": "/blog/2014/07/28/community-roundup-20.md", - "date": "2014-07-28", - "title": "Community Round-up #20", - "author": [ - "LoukaN" - ], - "excerpt": "

    It’s an exciting time for React as there are now more commits from open source contributors than from Facebook engineers! Keep up the good work :)

    \n", - "readingTime": "4 min read" - }, - { - "path": "/blog/2014/07/25/react-v0.11.1.md", - "date": "2014-07-25", - "title": "React v0.11.1", - "author": [ - "zpao" - ], - "excerpt": "

    Today we’re releasing React v0.11.1 to address a few small issues. Thanks to everybody who has reported them as they’ve begun upgrading.

    \n", - "readingTime": "2 min read" - }, - { - "path": "/blog/2014/07/17/react-v0.11.md", - "date": "2014-07-17", - "title": "React v0.11", - "author": [ - "zpao" - ], - "excerpt": "

    Update: We missed a few important changes in our initial post and changelog. We’ve updated this post with details about Descriptors and Prop Type Validation.

    \n", - "readingTime": "7 min read" - }, - { - "path": "/blog/2014/07/13/react-v0.11-rc1.md", - "date": "2014-07-13", - "title": "React v0.11 RC", - "author": [ - "zpao" - ], - "excerpt": "

    It’s that time again… we’re just about ready to ship a new React release! v0.11 includes a wide array of bug fixes and features. We highlighted some of the most important changes below, along with the full changelog.

    \n", - "readingTime": "5 min read" - }, - { - "path": "/blog/2014/06/27/community-roundup-19.md", - "date": "2014-06-27", - "title": "Community Round-up #19", - "author": [ - "chenglou" - ], - "excerpt": "

    React Meetups!

    \n", - "readingTime": "3 min read" - }, - { - "path": "/blog/2014/05/29/one-year-of-open-source-react.md", - "date": "2014-05-29", - "title": "One Year of Open-Source React", - "author": [ - "chenglou" - ], - "excerpt": "

    Today marks the one-year open-source anniversary of React.

    \n", - "readingTime": "2 min read" - }, - { - "path": "/blog/2014/05/06/flux.md", - "date": "2014-05-06", - "title": "Flux: An Application Architecture for React", - "author": [ - "fisherwebdev", - "jingc" - ], - "excerpt": "

    We recently spoke at one of f8’s breakout session about Flux, a data flow architecture that works well with React. Check out the video here:

    \n", - "readingTime": "2 min read" - }, - { - "path": "/blog/2014/04/04/reactnet.md", - "date": "2014-04-04", - "title": "Use React and JSX in ASP.NET MVC", - "author": [ - "Daniel15" - ], - "excerpt": "

    Today we’re happy to announce the initial release of

    \n", - "readingTime": "1 min read" - }, - { - "path": "/blog/2014/03/28/the-road-to-1.0.md", - "date": "2014-03-28", - "title": "The Road to 1.0", - "author": [ - "zpao" - ], - "excerpt": "

    When we launched React last spring, we purposefully decided not to call it 1.0. It was production ready, but we had plans to evolve APIs and behavior as we saw how people were using React, both internally and externally. We’ve learned a lot over the past 9 months and we’ve thought a lot about what 1.0 will mean for React. A couple weeks ago, I outlined [several projects][projects] that we have planned to take us to 1.0 and beyond. Today I’m writing a bit more about them to give our users a better insight into our plans.

    \n", - "readingTime": "4 min read" - }, - { - "path": "/blog/2014/03/21/react-v0.10.md", - "date": "2014-03-21", - "title": "React v0.10", - "author": [ - "zpao" - ], - "excerpt": "

    Hot on the heels of the release candidate earlier this week, we’re ready to call v0.10 done. The only major issue we discovered had to do with the react-tools package, which has been updated. We’ve copied over the changelog from the RC with some small clarifying changes.

    \n", - "readingTime": "4 min read" - }, - { - "path": "/blog/2014/03/19/react-v0.10-rc1.md", - "date": "2014-03-19", - "title": "React v0.10 RC", - "author": [ - "zpao" - ], - "excerpt": "

    v0.9 has only been out for a month, but we’re getting ready to push out v0.10 already. Unlike v0.9 which took a long time, we don’t have a long list of changes to talk about.

    \n", - "readingTime": "4 min read" - }, - { - "path": "/blog/2014/03/14/community-roundup-18.md", - "date": "2014-03-14", - "title": "Community Round-up #18", - "author": [ - "jgebhardt" - ], - "excerpt": "

    In this Round-up, we are taking a few closer looks at React’s interplay with different frameworks and architectures.

    \n", - "readingTime": "5 min read" - }, - { - "path": "/blog/2014/02/24/community-roundup-17.md", - "date": "2014-02-24", - "title": "Community Round-up #17", - "author": [ - "jgebhardt" - ], - "excerpt": "

    It’s exciting to see the number of real-world React applications and components skyrocket over the past months! This community round-up features a few examples of inspiring React applications and components.

    \n", - "readingTime": "3 min read" - }, - { - "path": "/blog/2014/02/20/react-v0.9.md", - "date": "2014-02-20", - "title": "React v0.9", - "author": [ - "sophiebits" - ], - "excerpt": "

    I’m excited to announce that today we’re releasing React v0.9, which incorporates many bug fixes and several new features since the last release. This release contains almost four months of work, including over 800 commits from over 70 committers!

    \n", - "readingTime": "7 min read" - }, - { - "path": "/blog/2014/02/16/react-v0.9-rc1.md", - "date": "2014-02-16", - "title": "React v0.9 RC", - "author": [ - "sophiebits" - ], - "excerpt": "

    We’re almost ready to release React v0.9! We’re posting a release candidate so that you can test your apps on it; we’d much prefer to find show-stopping bugs now rather than after we release.

    \n", - "readingTime": "6 min read" - }, - { - "path": "/blog/2014/02/15/community-roundup-16.md", - "date": "2014-02-15", - "title": "Community Round-up #16", - "author": [ - "jgebhardt" - ], - "excerpt": "

    There have been many posts recently covering the why and how of React. This week’s community round-up includes a collection of recent articles to help you get started with React, along with a few posts that explain some of the inner workings.

    \n", - "readingTime": "4 min read" - }, - { - "path": "/blog/2014/02/05/community-roundup-15.md", - "date": "2014-02-05", - "title": "Community Round-up #15", - "author": [ - "jgebhardt" - ], - "excerpt": "

    Interest in React seems to have surged ever since David Nolen (@swannodette)β€˜s introduction of Om in his post β€œThe Future of JavaScript MVC Frameworks”.

    \n", - "readingTime": "4 min read" - }, - { - "path": "/blog/2014/01/06/community-roundup-14.md", - "date": "2014-01-06", - "title": "Community Round-up #14", - "author": [ - "vjeux" - ], - "excerpt": "

    The theme of this first round-up of 2014 is integration. I’ve tried to assemble a list of articles and projects that use React in various environments.

    \n", - "readingTime": "3 min read" - }, - { - "path": "/blog/2014/01/02/react-chrome-developer-tools.md", - "date": "2014-01-02", - "title": "React Chrome Developer Tools", - "author": [ - "sebmarkbage" - ], - "excerpt": "

    With the new year, we thought you’d enjoy some new tools for debugging React code. Today we’re releasing the React Developer Tools, an extension to the Chrome Developer Tools. Download them from the Chrome Web Store.

    \n", - "readingTime": "2 min read" - }, - { - "path": "/blog/2013/12/30/community-roundup-13.md", - "date": "2013-12-30", - "title": "Community Round-up #13", - "author": [ - "vjeux" - ], - "excerpt": "

    Happy holidays! This blog post is a little-late Christmas present for all the React users. Hopefully it will inspire you to write awesome web apps in 2014!

    \n", - "readingTime": "4 min read" - }, - { - "path": "/blog/2013/12/23/community-roundup-12.md", - "date": "2013-12-23", - "title": "Community Round-up #12", - "author": [ - "vjeux" - ], - "excerpt": "

    React got featured on the front-page of Hacker News thanks to the Om library. If you try it out for the first time, take a look at the docs and do not hesitate to ask questions on the Google Group, IRC or Stack Overflow. We are trying our best to help you out!

    \n", - "readingTime": "4 min read" - }, - { - "path": "/blog/2013/12/19/react-v0.8.0.md", - "date": "2013-12-19", - "title": "React v0.8", - "author": [ - "zpao" - ], - "excerpt": "

    I’ll start by answering the obvious question:

    \n", - "readingTime": "2 min read" - }, - { - "path": "/blog/2013/12/18/react-v0.5.2-v0.4.2.md", - "date": "2013-12-18", - "title": "React v0.5.2, v0.4.2", - "author": [ - "zpao" - ], - "excerpt": "

    Today we’re releasing an update to address a potential XSS vulnerability that can arise when using user data as a key. Typically β€œsafe” data is used for a key, for example, an id from your database, or a unique hash. However there are cases where it may be reasonable to use user generated content. A carefully crafted piece of content could result in arbitrary JS execution. While we make a very concerted effort to ensure all text is escaped before inserting it into the DOM, we missed one case. Immediately following the discovery of this vulnerability, we performed an audit to ensure we this was the only such vulnerability.

    \n", - "readingTime": "2 min read" - }, - { - "path": "/blog/2013/11/18/community-roundup-11.md", - "date": "2013-11-18", - "title": "Community Round-up #11", - "author": [ - "vjeux" - ], - "excerpt": "

    This round-up is the proof that React has taken off from its Facebook’s root: it features three in-depth presentations of React done by external people. This is awesome, keep them coming!

    \n", - "readingTime": "4 min read" - }, - { - "path": "/blog/2013/11/06/community-roundup-10.md", - "date": "2013-11-06", - "title": "Community Round-up #10", - "author": [ - "vjeux" - ], - "excerpt": "

    This is the 10th round-up already and React has come quite far since it was open sourced. Almost all new web projects at Khan Academy, Facebook, and Instagram are being developed using React. React has been deployed in a variety of contexts: a Chrome extension, a Windows 8 application, mobile websites, and desktop websites supporting Internet Explorer 8! Language-wise, React is not only being used within JavaScript but also CoffeeScript and ClojureScript.

    \n", - "readingTime": "6 min read" - }, - { - "path": "/blog/2013/10/29/react-v0-5-1.md", - "date": "2013-10-29", - "title": "React v0.5.1", - "author": [ - "zpao" - ], - "excerpt": "

    This release focuses on fixing some small bugs that have been uncovered over the past two weeks. I would like to thank everybody involved, specifically members of the community who fixed half of the issues found. Thanks to [Sophie Alpert][1], [Andrey Popp][2], and [Laurence Rowe][3] for their contributions!

    \n", - "readingTime": "1 min read" - }, - { - "path": "/blog/2013/10/16/react-v0.5.0.md", - "date": "2013-10-16", - "title": "React v0.5", - "author": [ - "zpao" - ], - "excerpt": "

    This release is the result of several months of hard work from members of the team and the community. While there are no groundbreaking changes in core, we’ve worked hard to improve performance and memory usage. We’ve also worked hard to make sure we are being consistent in our usage of DOM properties.

    \n", - "readingTime": "4 min read" - }, - { - "path": "/blog/2013/10/03/community-roundup-9.md", - "date": "2013-10-03", - "title": "Community Round-up #9", - "author": [ - "vjeux" - ], - "excerpt": "

    We organized a React hackathon last week-end in the Facebook Seattle office. 50 people, grouped into 15 teams, came to hack for a day on React. It was a lot of fun and we’ll probably organize more in the future.

    \n", - "readingTime": "3 min read" - }, - { - "path": "/blog/2013/09/24/community-roundup-8.md", - "date": "2013-09-24", - "title": "Community Round-up #8", - "author": [ - "vjeux" - ], - "excerpt": "

    A lot has happened in the month since our last update. Here are some of the more interesting things we’ve found. But first, we have a couple updates before we share links.

    \n", - "readingTime": "6 min read" - }, - { - "path": "/blog/2013/08/26/community-roundup-7.md", - "date": "2013-08-26", - "title": "Community Round-up #7", - "author": [ - "vjeux" - ], - "excerpt": "

    It’s been three months since we open sourced React and it is going well. Some stats so far:

    \n", - "readingTime": "3 min read" - }, - { - "path": "/blog/2013/08/19/use-react-and-jsx-in-python-applications.md", - "date": "2013-08-19", - "title": "Use React and JSX in Python Applications", - "author": [ - "kmeht" - ], - "excerpt": "

    Today we’re happy to announce the initial release of PyReact, which makes it easier to use React and JSX in your Python applications. It’s designed to provide an API to transform your JSX files into JavaScript, as well as provide access to the latest React source files.

    \n", - "readingTime": "2 min read" - }, - { - "path": "/blog/2013/08/05/community-roundup-6.md", - "date": "2013-08-05", - "title": "Community Round-up #6", - "author": [ - "vjeux" - ], - "excerpt": "

    This is the first Community Round-up where none of the items are from Facebook/Instagram employees. It’s great to see the adoption of React growing.

    \n", - "readingTime": "3 min read" - }, - { - "path": "/blog/2013/07/30/use-react-and-jsx-in-ruby-on-rails.md", - "date": "2013-07-30", - "title": "Use React and JSX in Ruby on Rails", - "author": [ - "zpao" - ], - "excerpt": "

    Today we’re releasing a gem to make it easier to use React and JSX in Ruby on Rails applications: react-rails.

    \n", - "readingTime": "2 min read" - }, - { - "path": "/blog/2013/07/26/react-v0-4-1.md", - "date": "2013-07-26", - "title": "React v0.4.1", - "author": [ - "zpao" - ], - "excerpt": "

    React v0.4.1 is a small update, mostly containing correctness fixes. Some code has been restructured internally but those changes do not impact any of our public APIs.

    \n", - "readingTime": "1 min read" - }, - { - "path": "/blog/2013/07/23/community-roundup-5.md", - "date": "2013-07-23", - "title": "Community Round-up #5", - "author": [ - "vjeux" - ], - "excerpt": "

    We launched the React Facebook Page along with the React v0.4 launch. 700 people already liked it to get updated on the project :)

    \n", - "readingTime": "4 min read" - }, - { - "path": "/blog/2013/07/17/react-v0-4-0.md", - "date": "2013-07-17", - "title": "React v0.4.0", - "author": [ - "zpao" - ], - "excerpt": "

    Over the past 2 months we’ve been taking feedback and working hard to make React even better. We fixed some bugs, made some under-the-hood improvements, and added several features that we think will improve the experience developing with React. Today we’re proud to announce the availability of React v0.4!

    \n", - "readingTime": "3 min read" - }, - { - "path": "/blog/2013/07/11/react-v0-4-prop-validation-and-default-values.md", - "date": "2013-07-11", - "title": "New in React v0.4: Prop Validation and Default Values", - "author": [ - "zpao" - ], - "excerpt": "

    Many of the questions we got following the public launch of React revolved around props, specifically that people wanted to do validation and to make sure their components had sensible defaults.

    \n", - "readingTime": "2 min read" - }, - { - "path": "/blog/2013/07/03/community-roundup-4.md", - "date": "2013-07-03", - "title": "Community Round-up #4", - "author": [ - "vjeux" - ], - "excerpt": "

    React reconciliation process appears to be very well suited to implement a text editor with a live preview as people at Khan Academy show us.

    \n", - "readingTime": "3 min read" - }, - { - "path": "/blog/2013/07/02/react-v0-4-autobind-by-default.md", - "date": "2013-07-02", - "title": "New in React v0.4: Autobind by Default", - "author": [ - "zpao" - ], - "excerpt": "

    React v0.4 is very close to completion. As we finish it off, we’d like to share with you some of the major changes we’ve made since v0.3. This is the first of several posts we’ll be making over the next week.

    \n", - "readingTime": "2 min read" - }, - { - "path": "/blog/2013/06/27/community-roundup-3.md", - "date": "2013-06-27", - "title": "Community Round-up #3", - "author": [ - "vjeux" - ], - "excerpt": "

    The highlight of this week is that an interaction-heavy app has been ported to React. React components are solving issues they had with nested views.

    \n", - "readingTime": "4 min read" - }, - { - "path": "/blog/2013/06/21/react-v0-3-3.md", - "date": "2013-06-21", - "title": "React v0.3.3", - "author": [ - "zpao" - ], - "excerpt": "

    We have a ton of great stuff coming in v0.4, but in the meantime we’re releasing v0.3.3. This release addresses some small issues people were having and simplifies our tools to make them easier to use.

    \n", - "readingTime": "1 min read" - }, - { - "path": "/blog/2013/06/19/community-roundup-2.md", - "date": "2013-06-19", - "title": "Community Round-up #2", - "author": [ - "vjeux" - ], - "excerpt": "

    Since the launch we have received a lot of feedback and are actively working on React 0.4. In the meantime, here are the highlights of this week.

    \n", - "readingTime": "4 min read" - }, - { - "path": "/blog/2013/06/12/community-roundup.md", - "date": "2013-06-12", - "title": "Community Round-up #1", - "author": [ - "vjeux" - ], - "excerpt": "

    React was open sourced two weeks ago and it’s time for a little round-up of what has been going on.

    \n", - "readingTime": "3 min read" - }, - { - "path": "/blog/2013/06/05/why-react.md", - "date": "2013-06-05", - "title": "Why did we build React?", - "author": [ - "petehunt" - ], - "excerpt": "

    There are a lot of JavaScript MVC frameworks out there. Why did we build React

    \n", - "readingTime": "3 min read" - }, - { - "path": "/blog/2013/06/02/jsfiddle-integration.md", - "date": "2013-06-02", - "title": "JSFiddle Integration", - "author": [ - "vjeux" - ], - "excerpt": "

    JSFiddle just announced support for React. This is an exciting news as it makes collaboration on snippets of code a lot easier. You can play around this base React JSFiddle, fork it and share it! A fiddle without JSX is also available.

    \n", - "readingTime": "1 min read" - } - ] -} \ No newline at end of file diff --git a/beta/src/blogIndexRecent.json b/beta/src/blogIndexRecent.json deleted file mode 100644 index 8bf964b5c..000000000 --- a/beta/src/blogIndexRecent.json +++ /dev/null @@ -1,207 +0,0 @@ -{ - "title": "Recent Posts", - "heading": true, - "path": "/blog", - "routes": [ - { - "path": "/blog/2020/08/10/react-v17-rc.md", - "date": "2020-08-10", - "title": "React v17.0 Release Candidate: No New Features", - "author": ["gaearon", "rachelnabors"], - "excerpt": "

    Today, we are publishing the first Release Candidate for React 17. It has been two and a half years since the previous major release of React, which is a long time even by our standards! In this blog post, we will describe the role of this major release, what changes you can expect in it, and how you can try this release.

    \n", - "readingTime": "20 min read" - }, - { - "path": "/blog/2020/02/26/react-v16.13.0.md", - "date": "2020-02-26", - "title": "React v16.13.0", - "author": ["threepointone"], - "excerpt": "

    Today we are releasing React 16.13.0. It contains bugfixes and new deprecation warnings to help prepare for a future major release.

    \n", - "readingTime": "7 min read" - }, - { - "path": "/blog/2019/11/06/building-great-user-experiences-with-concurrent-mode-and-suspense.md", - "date": "2019-11-06", - "title": "Building Great User Experiences with Concurrent Mode and Suspense", - "author": ["josephsavona"], - "excerpt": "

    At React Conf 2019 we announced an experimental release of React that supports Concurrent Mode and Suspense. In this post we’ll introduce best practices for using them that we’ve identified through the process of building the new facebook.com.

    \n", - "readingTime": "17 min read" - }, - { - "path": "/blog/2019/10/22/react-release-channels.md", - "date": "2019-10-22", - "title": "Preparing for the Future with React Prereleases", - "author": ["acdlite"], - "excerpt": "

    To share upcoming changes with our partners in the React ecosystem, we’re establishing official prerelease channels. We hope this process will help us make changes to React with confidence, and give developers the opportunity to try out experimental features.

    \n", - "readingTime": "7 min read" - }, - { - "path": "/blog/2019/08/15/new-react-devtools.md", - "date": "2019-08-15", - "title": "Introducing the New React DevTools", - "author": ["bvaughn"], - "excerpt": "

    We are excited to announce a new release of the React Developer Tools, available today in Chrome, Firefox, and (Chromium) Edge!

    \n", - "readingTime": "2 min read" - }, - { - "path": "/blog/2019/08/08/react-v16.9.0.md", - "date": "2019-08-08", - "title": "React v16.9.0 and the Roadmap Update", - "author": ["gaearon", "bvaughn"], - "excerpt": "

    Today we are releasing React 16.9. It contains several new features, bugfixes, and new deprecation warnings to help prepare for a future major release.

    \n", - "readingTime": "11 min read" - }, - { - "path": "/blog/2019/02/23/is-react-translated-yet.md", - "date": "2019-02-23", - "title": "Is React Translated Yet? Β‘SΓ­! Sim! はい!", - "author": ["tesseralis"], - "excerpt": "

    We’re excited to announce an ongoing effort to maintain official translations of the React documentation website into different languages. Thanks to the dedicated efforts of React community members from around the world, React is now being translated into over 30 languages! You can find them on the new Languages page.

    \n", - "readingTime": "7 min read" - }, - { - "path": "/blog/2019/02/06/react-v16.8.0.md", - "date": "2019-02-06", - "title": "React v16.8: The One With Hooks", - "author": ["gaearon"], - "excerpt": "

    With React 16.8, React Hooks are available in a stable release!

    \n", - "readingTime": "7 min read" - }, - { - "path": "/blog/2018/12/19/react-v-16-7.md", - "date": "2018-12-19", - "title": "React v16.7: No, This Is Not the One With Hooks", - "author": ["acdlite"], - "excerpt": "

    Our latest release includes an important performance bugfix for React.lazy. Although there are no API changes, we’re releasing it as a minor instead of a patch.

    \n", - "readingTime": "3 min read" - }, - { - "path": "/blog/2018/11/27/react-16-roadmap.md", - "date": "2018-11-27", - "title": "React 16.x Roadmap", - "author": ["gaearon"], - "excerpt": "

    You might have heard about features like β€œHooks”, β€œSuspense”, and β€œConcurrent Rendering” in the previous blog posts and talks. In this post, we’ll look at how they fit together and the expected timeline for their availability in a stable release of React.

    \n", - "readingTime": "14 min read" - }, - { - "path": "/blog/2018/11/13/react-conf-recap.md", - "date": "2018-11-13", - "title": "React Conf recap: Hooks, Suspense, and Concurrent Rendering", - "author": ["tomocchino"], - "excerpt": "

    This year’s React Conf took place on October 25 and 26 in Henderson, Nevada, where more than 600 attendees gathered to discuss the latest in UI engineering.

    \n", - "readingTime": "2 min read" - }, - { - "path": "/blog/2018/10/23/react-v-16-6.md", - "date": "2018-10-23", - "title": "React v16.6.0: lazy, memo and contextType", - "author": ["sebmarkbage"], - "excerpt": "

    Today we’re releasing React 16.6 with a few new convenient features. A form of PureComponent/shouldComponentUpdate for function components, a way to do code splitting using Suspense and an easier way to consume Context from class components.

    \n", - "readingTime": "5 min read" - }, - { - "path": "/blog/2018/10/01/create-react-app-v2.md", - "date": "2018-10-01", - "title": "Create React App 2.0: BabelΒ 7, Sass, and More", - "author": ["timer", "gaearon"], - "excerpt": "

    Create React App 2.0 has been released today, and it brings a year’s worth of improvements in a single dependency update.

    \n", - "readingTime": "6 min read" - }, - { - "path": "/blog/2018/09/10/introducing-the-react-profiler.md", - "date": "2018-09-10", - "title": "Introducing the React Profiler", - "author": ["bvaughn"], - "excerpt": "

    React 16.5 adds support for a new DevTools profiler plugin.

    \n", - "readingTime": "8 min read" - }, - { - "path": "/blog/2018/08/01/react-v-16-4-2.md", - "date": "2018-08-01", - "title": "React v16.4.2: Server-side vulnerability fix", - "author": ["gaearon"], - "excerpt": "

    We discovered a minor vulnerability that might affect some apps using ReactDOMServer. We are releasing a patch version for every affected React minor release so that you can upgrade with no friction. Read on for more details.

    \n", - "readingTime": "4 min read" - }, - { - "path": "/blog/2018/06/07/you-probably-dont-need-derived-state.md", - "date": "2018-06-07", - "title": "You Probably Don't Need Derived State", - "author": ["bvaughn"], - "excerpt": "

    React 16.4 included a bugfix for getDerivedStateFromProps which caused some existing bugs in React components to reproduce more consistently. If this release exposed a case where your application was using an anti-pattern and didn’t work properly after the fix, we’re sorry for the churn. In this post, we will explain some common anti-patterns with derived state and our preferred alternatives.

    \n", - "readingTime": "14 min read" - }, - { - "path": "/blog/2018/05/23/react-v-16-4.md", - "date": "2018-05-23", - "title": "React v16.4.0: Pointer Events", - "author": ["acdlite"], - "excerpt": "

    The latest minor release adds support for an oft-requested feature: pointer events!

    \n", - "readingTime": "5 min read" - }, - { - "path": "/blog/2018/03/29/react-v-16-3.md", - "date": "2018-03-29", - "title": "React v16.3.0: New lifecycles and context API", - "author": ["bvaughn"], - "excerpt": "

    A few days ago, we wrote a post about upcoming changes to our legacy lifecycle methods, including gradual migration strategies. In React 16.3.0, we are adding a few new lifecycle methods to assist with that migration. We are also introducing new APIs for long requested features: an official context API, a ref forwarding API, and an ergonomic ref API.

    \n", - "readingTime": "6 min read" - }, - { - "path": "/blog/2018/03/27/update-on-async-rendering.md", - "date": "2018-03-27", - "title": "Update on Async Rendering", - "author": ["bvaughn"], - "excerpt": "

    For over a year, the React team has been working to implement asynchronous rendering. Last month during his talk at JSConf Iceland, Dan unveiled some of the exciting new possibilities async rendering unlocks. Now we’d like to share with you some of the lessons we’ve learned while working on these features, and some recipes to help prepare your components for async rendering when it launches.

    \n", - "readingTime": "12 min read" - }, - { - "path": "/blog/2018/03/01/sneak-peek-beyond-react-16.md", - "date": "2018-03-01", - "title": "Sneak Peek: Beyond React 16", - "author": ["sophiebits"], - "excerpt": "

    Dan Abramov from our team just spoke at JSConf Iceland 2018 with a preview of some new features we’ve been working on in React. The talk opens with a question: β€œWith vast differences in computing power and network speed, how do we deliver the best user experience for everyone?”

    \n", - "readingTime": "2 min read" - }, - { - "path": "/blog/2017/12/15/improving-the-repository-infrastructure.md", - "date": "2017-12-15", - "title": "Behind the Scenes: Improving the Repository Infrastructure", - "author": ["gaearon", "bvaughn"], - "excerpt": "

    As we worked on React 16, we revamped the folder structure and much of the build tooling in the React repository. Among other things, we introduced projects such as Rollup, Prettier, and Google Closure Compiler into our workflow. People often ask us questions about how we use those tools. In this post, we would like to share some of the changes that we’ve made to our build and test infrastructure in 2017, and what motivated them.

    \n", - "readingTime": "30 min read" - }, - { - "path": "/blog/2017/12/07/introducing-the-react-rfc-process.md", - "date": "2017-12-07", - "title": "Introducing the React RFC Process", - "author": ["acdlite"], - "excerpt": "

    We’re adopting an RFC (β€œrequest for comments”) process for contributing ideas to React.

    \n", - "readingTime": "2 min read" - }, - { - "path": "/blog/2017/11/28/react-v16.2.0-fragment-support.md", - "date": "2017-11-28", - "title": "React v16.2.0: Improved Support for Fragments", - "author": ["clemmy"], - "excerpt": "

    React 16.2 is now available! The biggest addition is improved support for returning multiple children from a component’s render method. We call this feature fragments:

    \n", - "readingTime": "8 min read" - }, - { - "path": "/blog/2017/09/26/react-v16.0.md", - "date": "2017-09-26", - "title": "React v16.0", - "author": ["acdlite"], - "excerpt": "

    We’re excited to announce the release of React v16.0! Among the changes are some long-standing feature requests, including fragments, error boundaries, portals, support for custom DOM attributes, improved server-side rendering, and reduced file size.

    \n", - "readingTime": "11 min read" - }, - { - "path": "/blog/2017/09/25/react-v15.6.2.md", - "date": "2017-09-25", - "title": "React v15.6.2", - "author": ["nhunzaker"], - "excerpt": "

    Today we’re sending out React 15.6.2. In 15.6.1, we shipped a few fixes for change events and inputs that had some unintended consequences. Those regressions have been ironed out, and we’ve also included a few more fixes to improve the stability of React across all browsers.

    \n", - "readingTime": "3 min read" - } - ] -} diff --git a/beta/src/components/Breadcrumbs.tsx b/beta/src/components/Breadcrumbs.tsx deleted file mode 100644 index bc8078bf9..000000000 --- a/beta/src/components/Breadcrumbs.tsx +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Copyright (c) Facebook, Inc. and its affiliates. - */ - -import * as React from 'react'; -import {useRouteMeta} from 'components/Layout/useRouteMeta'; -import Link from 'next/link'; - -function Breadcrumbs() { - const {breadcrumbs} = useRouteMeta(); - if (!breadcrumbs) return null; - return ( -
    - {breadcrumbs.map( - (crumb, i) => - crumb.path && ( -
    - - - - {crumb.title} - - - - - - - - -
    - ) - )} -
    - ); -} - -export default Breadcrumbs; diff --git a/beta/src/components/Button.tsx b/beta/src/components/Button.tsx deleted file mode 100644 index 9d4d0cf2b..000000000 --- a/beta/src/components/Button.tsx +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Copyright (c) Facebook, Inc. and its affiliates. - */ - -import * as React from 'react'; -import cn from 'classnames'; - -interface ButtonProps { - children: React.ReactNode; - onClick?: (event: React.MouseEvent) => void; - active: boolean; - className?: string; - style?: Record; -} - -export function Button({ - children, - onClick, - active, - className, - style, -}: ButtonProps) { - return ( - - ); -} - -Button.defaultProps = { - active: false, - style: {}, -}; - -export default Button; diff --git a/beta/src/components/ButtonLink.tsx b/beta/src/components/ButtonLink.tsx deleted file mode 100644 index 964056ed7..000000000 --- a/beta/src/components/ButtonLink.tsx +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Copyright (c) Facebook, Inc. and its affiliates. - */ - -import * as React from 'react'; -import cn from 'classnames'; -import NextLink from 'next/link'; - -interface ButtonLinkProps { - size?: 'md' | 'lg'; - type?: 'primary' | 'secondary'; - label?: string; - target?: '_self' | '_blank'; -} - -function ButtonLink({ - href, - className, - children, - type = 'primary', - size = 'md', - label, - target = '_self', - ...props -}: JSX.IntrinsicElements['a'] & ButtonLinkProps) { - const classes = cn( - className, - 'inline-flex font-bold items-center border-2 border-transparent outline-none focus:ring-1 focus:ring-offset-2 focus:ring-link active:bg-link active:text-white active:ring-0 active:ring-offset-0 leading-normal', - { - 'bg-link text-white hover:bg-opacity-80': type === 'primary', - 'bg-secondary-button dark:bg-secondary-button-dark text-primary dark:text-primary-dark hover:text-link focus:bg-link focus:text-white focus:border-link focus:border-2': - type === 'secondary', - 'text-lg rounded-lg p-4': size === 'lg', - 'text-base rounded-lg px-4 py-1.5': size === 'md', - } - ); - return ( - - - {children} - - - ); -} - -export default ButtonLink; diff --git a/beta/src/components/DocsFooter.tsx b/beta/src/components/DocsFooter.tsx deleted file mode 100644 index c2ab02255..000000000 --- a/beta/src/components/DocsFooter.tsx +++ /dev/null @@ -1,93 +0,0 @@ -/* - * Copyright (c) Facebook, Inc. and its affiliates. - */ - -import NextLink from 'next/link'; -import * as React from 'react'; -import cn from 'classnames'; -import {removeFromLast} from 'utils/removeFromLast'; -import {IconNavArrow} from './Icon/IconNavArrow'; -import {RouteMeta} from './Layout/useRouteMeta'; - -export type DocsPageFooterProps = Pick< - RouteMeta, - 'route' | 'nextRoute' | 'prevRoute' ->; - -function areEqual(prevProps: DocsPageFooterProps, props: DocsPageFooterProps) { - return prevProps.route?.path === props.route?.path; -} - -export const DocsPageFooter = React.memo( - function DocsPageFooter({nextRoute, prevRoute, route}) { - if (!route || route?.heading) { - return null; - } - - return ( - <> - {prevRoute?.path || nextRoute?.path ? ( - <> -
    - {prevRoute?.path ? ( - - ) : ( -
    - )} - - {nextRoute?.path ? ( - - ) : ( -
    - )} -
    - - ) : null} - - ); - }, - areEqual -); - -function FooterLink({ - href, - title, - type, -}: { - href: string; - title: string; - type: 'Previous' | 'Next'; -}) { - return ( - - - - - - {type} - - {title} - - - - ); -} - -DocsPageFooter.displayName = 'DocsPageFooter'; diff --git a/beta/src/components/ExternalLink.tsx b/beta/src/components/ExternalLink.tsx deleted file mode 100644 index 4ab7831da..000000000 --- a/beta/src/components/ExternalLink.tsx +++ /dev/null @@ -1,20 +0,0 @@ -/* - * Copyright (c) Facebook, Inc. and its affiliates. - */ - -import * as React from 'react'; - -export function ExternalLink({ - href, - target, - children, - ...props -}: JSX.IntrinsicElements['a']) { - return ( - - {children} - - ); -} - -ExternalLink.displayName = 'ExternalLink'; diff --git a/beta/src/components/Icon/IconArrow.tsx b/beta/src/components/Icon/IconArrow.tsx deleted file mode 100644 index 6c93c7758..000000000 --- a/beta/src/components/Icon/IconArrow.tsx +++ /dev/null @@ -1,30 +0,0 @@ -/* - * Copyright (c) Facebook, Inc. and its affiliates. - */ - -import * as React from 'react'; -import cn from 'classnames'; - -export const IconArrow = React.memo< - JSX.IntrinsicElements['svg'] & { - displayDirection: 'left' | 'right' | 'up' | 'down'; - } ->(function IconArrow({displayDirection, className, ...rest}) { - return ( - - - - - ); -}); - -IconArrow.displayName = 'IconArrow'; diff --git a/beta/src/components/Icon/IconArrowSmall.tsx b/beta/src/components/Icon/IconArrowSmall.tsx deleted file mode 100644 index e415b9fac..000000000 --- a/beta/src/components/Icon/IconArrowSmall.tsx +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Copyright (c) Facebook, Inc. and its affiliates. - */ - -import * as React from 'react'; -import cn from 'classnames'; - -export const IconArrowSmall = React.memo< - JSX.IntrinsicElements['svg'] & { - displayDirection: 'left' | 'right' | 'up' | 'down'; - } ->(function IconArrowSmall({displayDirection, className, ...rest}) { - const classes = cn(className, { - 'transform rotate-180': displayDirection === 'left', - 'transform rotate-90': displayDirection === 'down', - }); - return ( - - - - ); -}); - -IconArrowSmall.displayName = 'IconArrowSmall'; diff --git a/beta/src/components/Icon/IconChevron.tsx b/beta/src/components/Icon/IconChevron.tsx deleted file mode 100644 index dfd77b11f..000000000 --- a/beta/src/components/Icon/IconChevron.tsx +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Copyright (c) Facebook, Inc. and its affiliates. - */ - -import * as React from 'react'; -import cn from 'classnames'; - -export const IconChevron = React.memo< - JSX.IntrinsicElements['svg'] & { - displayDirection: 'up' | 'down' | 'left' | 'right'; - } ->(function IconChevron({className, displayDirection, ...rest}) { - const classes = cn( - { - 'transform rotate-0': displayDirection === 'down', - 'transform rotate-90': displayDirection === 'left', - 'transform rotate-180': displayDirection === 'up', - 'transform -rotate-90': displayDirection === 'right', - }, - className - ); - return ( - - - - - - - ); -}); - -IconChevron.displayName = 'IconChevron'; diff --git a/beta/src/components/Icon/IconClose.tsx b/beta/src/components/Icon/IconClose.tsx deleted file mode 100644 index c31090302..000000000 --- a/beta/src/components/Icon/IconClose.tsx +++ /dev/null @@ -1,28 +0,0 @@ -/* - * Copyright (c) Facebook, Inc. and its affiliates. - */ - -import * as React from 'react'; - -export const IconClose = React.memo( - function IconClose(props) { - return ( - - - - - ); - } -); - -IconClose.displayName = 'IconClose'; diff --git a/beta/src/components/Icon/IconCodeBlock.tsx b/beta/src/components/Icon/IconCodeBlock.tsx deleted file mode 100644 index 9bb678c4b..000000000 --- a/beta/src/components/Icon/IconCodeBlock.tsx +++ /dev/null @@ -1,26 +0,0 @@ -/* - * Copyright (c) Facebook, Inc. and its affiliates. - */ - -import * as React from 'react'; - -export const IconCodeBlock = React.memo( - function IconCodeBlock({className}) { - return ( - - - - ); - } -); - -IconCodeBlock.displayName = 'IconCodeBlock'; diff --git a/beta/src/components/Icon/IconCopy.tsx b/beta/src/components/Icon/IconCopy.tsx deleted file mode 100644 index 552b30c6f..000000000 --- a/beta/src/components/Icon/IconCopy.tsx +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Copyright (c) Facebook, Inc. and its affiliates. - */ - -import * as React from 'react'; - -export const IconCopy = React.memo( - function IconCopy({className}) { - return ( - - {' '} - - - ); - } -); - -IconCopy.displayName = 'IconCopy'; diff --git a/beta/src/components/Icon/IconDeepDive.tsx b/beta/src/components/Icon/IconDeepDive.tsx deleted file mode 100644 index c68635350..000000000 --- a/beta/src/components/Icon/IconDeepDive.tsx +++ /dev/null @@ -1,26 +0,0 @@ -/* - * Copyright (c) Facebook, Inc. and its affiliates. - */ - -import * as React from 'react'; - -export const IconDeepDive = React.memo( - function IconDeepDive({className}) { - return ( - - - - ); - } -); - -IconDeepDive.displayName = 'IconDeepDive'; diff --git a/beta/src/components/Icon/IconError.tsx b/beta/src/components/Icon/IconError.tsx deleted file mode 100644 index 71c4a7c9b..000000000 --- a/beta/src/components/Icon/IconError.tsx +++ /dev/null @@ -1,24 +0,0 @@ -/* - * Copyright (c) Facebook, Inc. and its affiliates. - */ - -import * as React from 'react'; - -export const IconError = React.memo( - function IconError({className}) { - return ( - - - - - - ); - } -); - -IconError.displayName = 'IconError'; diff --git a/beta/src/components/Icon/IconFacebookCircle.tsx b/beta/src/components/Icon/IconFacebookCircle.tsx deleted file mode 100644 index d04017b36..000000000 --- a/beta/src/components/Icon/IconFacebookCircle.tsx +++ /dev/null @@ -1,22 +0,0 @@ -/* - * Copyright (c) Facebook, Inc. and its affiliates. - */ - -import * as React from 'react'; - -export const IconFacebookCircle = React.memo( - function IconFacebookCircle(props) { - return ( - - - - - ); - } -); diff --git a/beta/src/components/Icon/IconGitHub.tsx b/beta/src/components/Icon/IconGitHub.tsx deleted file mode 100644 index dee377e7c..000000000 --- a/beta/src/components/Icon/IconGitHub.tsx +++ /dev/null @@ -1,22 +0,0 @@ -/* - * Copyright (c) Facebook, Inc. and its affiliates. - */ - -import * as React from 'react'; - -export const IconGitHub = React.memo( - function IconGitHub(props) { - return ( - - - - ); - } -); - -IconGitHub.displayName = 'IconGitHub'; diff --git a/beta/src/components/Icon/IconGotcha.tsx b/beta/src/components/Icon/IconGotcha.tsx deleted file mode 100644 index 8342cbb6f..000000000 --- a/beta/src/components/Icon/IconGotcha.tsx +++ /dev/null @@ -1,26 +0,0 @@ -/* - * Copyright (c) Facebook, Inc. and its affiliates. - */ - -import * as React from 'react'; - -export const IconGotcha = React.memo( - function IconGotcha({className}) { - return ( - - - - ); - } -); - -IconGotcha.displayName = 'IconGotcha'; diff --git a/beta/src/components/Icon/IconHamburger.tsx b/beta/src/components/Icon/IconHamburger.tsx deleted file mode 100644 index c4653d589..000000000 --- a/beta/src/components/Icon/IconHamburger.tsx +++ /dev/null @@ -1,28 +0,0 @@ -/* - * Copyright (c) Facebook, Inc. and its affiliates. - */ - -import * as React from 'react'; - -export const IconHamburger = React.memo( - function IconHamburger(props) { - return ( - - - - - - ); - } -); - -IconHamburger.displayName = 'IconHamburger'; diff --git a/beta/src/components/Icon/IconHint.tsx b/beta/src/components/Icon/IconHint.tsx deleted file mode 100644 index d27b7e119..000000000 --- a/beta/src/components/Icon/IconHint.tsx +++ /dev/null @@ -1,26 +0,0 @@ -/* - * Copyright (c) Facebook, Inc. and its affiliates. - */ - -import * as React from 'react'; -import cn from 'classnames'; - -export const IconHint = React.memo( - function IconHint({className}) { - return ( - - - - ); - } -); - -IconHint.displayName = 'IconHint'; diff --git a/beta/src/components/Icon/IconNavArrow.tsx b/beta/src/components/Icon/IconNavArrow.tsx deleted file mode 100644 index e153f48b4..000000000 --- a/beta/src/components/Icon/IconNavArrow.tsx +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Copyright (c) Facebook, Inc. and its affiliates. - */ - -import * as React from 'react'; -import cn from 'classnames'; - -export const IconNavArrow = React.memo< - JSX.IntrinsicElements['svg'] & { - displayDirection: 'right' | 'down' | 'left'; - } ->(function IconNavArrow({displayDirection = 'right', className, ...rest}) { - const classes = cn( - 'duration-100 ease-in transition', - { - 'transform rotate-0': displayDirection === 'down', - 'transform -rotate-90': displayDirection === 'right', - 'transform rotate-90': displayDirection === 'left', - }, - className - ); - - return ( - - - - - - - ); -}); - -IconNavArrow.displayName = 'IconNavArrow'; diff --git a/beta/src/components/Icon/IconNewPage.tsx b/beta/src/components/Icon/IconNewPage.tsx deleted file mode 100644 index d13b5069f..000000000 --- a/beta/src/components/Icon/IconNewPage.tsx +++ /dev/null @@ -1,25 +0,0 @@ -/* - * Copyright (c) Facebook, Inc. and its affiliates. - */ - -import * as React from 'react'; - -export const IconNewPage = React.memo( - function IconNewPage(props) { - return ( - - - - ); - } -); - -IconNewPage.displayName = 'IconNewPage'; diff --git a/beta/src/components/Icon/IconNote.tsx b/beta/src/components/Icon/IconNote.tsx deleted file mode 100644 index 7ddf92525..000000000 --- a/beta/src/components/Icon/IconNote.tsx +++ /dev/null @@ -1,26 +0,0 @@ -/* - * Copyright (c) Facebook, Inc. and its affiliates. - */ - -import * as React from 'react'; - -export const IconNote = React.memo( - function IconNote({className}) { - return ( - - - - ); - } -); - -IconNote.displayName = 'IconNote'; diff --git a/beta/src/components/Icon/IconRestart.tsx b/beta/src/components/Icon/IconRestart.tsx deleted file mode 100644 index 2e52fe6c2..000000000 --- a/beta/src/components/Icon/IconRestart.tsx +++ /dev/null @@ -1,25 +0,0 @@ -/* - * Copyright (c) Facebook, Inc. and its affiliates. - */ - -import * as React from 'react'; - -export const IconRestart = React.memo( - function IconRestart({className}) { - return ( - - - - ); - } -); - -IconRestart.displayName = 'IconRestart'; diff --git a/beta/src/components/Icon/IconRss.tsx b/beta/src/components/Icon/IconRss.tsx deleted file mode 100644 index 4cd10de44..000000000 --- a/beta/src/components/Icon/IconRss.tsx +++ /dev/null @@ -1,29 +0,0 @@ -/* - * Copyright (c) Facebook, Inc. and its affiliates. - */ - -import * as React from 'react'; - -export const IconRss = React.memo( - function IconRss(props) { - return ( - - - - - - ); - } -); - -IconRss.displayName = 'IconLogo'; diff --git a/beta/src/components/Icon/IconSearch.tsx b/beta/src/components/Icon/IconSearch.tsx deleted file mode 100644 index a13fbfad1..000000000 --- a/beta/src/components/Icon/IconSearch.tsx +++ /dev/null @@ -1,24 +0,0 @@ -/* - * Copyright (c) Facebook, Inc. and its affiliates. - */ - -import * as React from 'react'; - -export const IconSearch = React.memo( - function IconSearch(props) { - return ( - - - - ); - } -); - -IconSearch.displayName = 'IconSearch'; diff --git a/beta/src/components/Icon/IconTwitter.tsx b/beta/src/components/Icon/IconTwitter.tsx deleted file mode 100644 index 1e113c9eb..000000000 --- a/beta/src/components/Icon/IconTwitter.tsx +++ /dev/null @@ -1,24 +0,0 @@ -/* - * Copyright (c) Facebook, Inc. and its affiliates. - */ - -import * as React from 'react'; - -export const IconTwitter = React.memo( - function IconTwitter(props) { - return ( - - - - - ); - } -); - -IconTwitter.displayName = 'IconTwitter'; diff --git a/beta/src/components/Icon/IconWarning.tsx b/beta/src/components/Icon/IconWarning.tsx deleted file mode 100644 index 09a4e03e7..000000000 --- a/beta/src/components/Icon/IconWarning.tsx +++ /dev/null @@ -1,28 +0,0 @@ -/* - * Copyright (c) Facebook, Inc. and its affiliates. - */ - -import * as React from 'react'; - -export const IconWarning = React.memo( - function IconWarning({className}) { - return ( - - - - - - - ); - } -); - -IconWarning.displayName = 'IconWarning'; diff --git a/beta/src/components/Layout/Footer.tsx b/beta/src/components/Layout/Footer.tsx deleted file mode 100644 index dc08d4d6a..000000000 --- a/beta/src/components/Layout/Footer.tsx +++ /dev/null @@ -1,183 +0,0 @@ -/* - * Copyright (c) Facebook, Inc. and its affiliates. - */ - -import * as React from 'react'; -import NextLink from 'next/link'; -import cn from 'classnames'; -import {ExternalLink} from 'components/ExternalLink'; -import {IconFacebookCircle} from 'components/Icon/IconFacebookCircle'; -import {IconTwitter} from 'components/Icon/IconTwitter'; - -export function Footer() { - const socialLinkClasses = 'hover:text-primary dark:text-primary-dark'; - return ( - <> -
    -
    -
    -
    -
    -
    - -
    - - - - - - - - - - - Open Source -
    -
    - ©{new Date().getFullYear()} -
    -
    -
    - - Learn React - - Quick Start - Installation - - Describing the UI - - - Adding Interactivity - - - Managing State - - - Escape Hatches - -
    -
    - - API Reference - - React APIs - React DOM APIs -
    -
    - - Community - - - Code of Conduct - - - Acknowledgements - - - Meet the Team - - {/* Community Resources */} -
    -
    - More - {/* Tutorial */} - {/* Blog */} - {/* Acknowledgements */} - - React Native - - - Privacy - - - Terms - -
    - - - - - - -
    -
    -
    -
    -
    - - ); -} - -function FooterLink({ - href, - children, - isHeader = false, -}: { - href?: string; - children: React.ReactNode; - isHeader?: boolean; -}) { - const classes = cn('border-b inline-block border-transparent', { - 'text-sm text-primary dark:text-primary-dark': !isHeader, - 'text-md text-secondary dark:text-secondary-dark my-2 font-bold': isHeader, - 'hover:border-gray-10': href, - }); - - if (!href) { - return
    {children}
    ; - } - - if (href.startsWith('https://')) { - return ( -
    - - {children} - -
    - ); - } - - return ( -
    - - {children} - -
    - ); -} diff --git a/beta/src/components/Layout/LayoutAPI.tsx b/beta/src/components/Layout/LayoutAPI.tsx deleted file mode 100644 index ceebaa322..000000000 --- a/beta/src/components/Layout/LayoutAPI.tsx +++ /dev/null @@ -1,26 +0,0 @@ -/* - * Copyright (c) Facebook, Inc. and its affiliates. - */ - -import * as React from 'react'; -import sidebarReference from 'sidebarReference.json'; -import {MarkdownPage, MarkdownProps} from './MarkdownPage'; -import {Page} from './Page'; -import {RouteItem} from './useRouteMeta'; - -interface PageFrontmatter { - title: string; - status: string; -} - -export default function withAPI(p: PageFrontmatter) { - function LayoutAPI(props: MarkdownProps) { - return ; - } - LayoutAPI.appShell = AppShell; - return LayoutAPI; -} - -function AppShell(props: {children: React.ReactNode}) { - return ; -} diff --git a/beta/src/components/Layout/LayoutHome.tsx b/beta/src/components/Layout/LayoutHome.tsx deleted file mode 100644 index 162ad7e5c..000000000 --- a/beta/src/components/Layout/LayoutHome.tsx +++ /dev/null @@ -1,26 +0,0 @@ -/* - * Copyright (c) Facebook, Inc. and its affiliates. - */ - -import * as React from 'react'; -import sidebarHome from 'sidebarHome.json'; -import {MarkdownPage, MarkdownProps} from './MarkdownPage'; -import {Page} from './Page'; -import {RouteItem} from './useRouteMeta'; - -interface PageFrontmatter { - title: string; - status: string; -} - -export default function withDocs(p: PageFrontmatter) { - function LayoutHome(props: MarkdownProps) { - return ; - } - LayoutHome.appShell = AppShell; - return LayoutHome; -} - -function AppShell(props: {children: React.ReactNode}) { - return ; -} diff --git a/beta/src/components/Layout/LayoutLearn.tsx b/beta/src/components/Layout/LayoutLearn.tsx deleted file mode 100644 index 9441b49d0..000000000 --- a/beta/src/components/Layout/LayoutLearn.tsx +++ /dev/null @@ -1,24 +0,0 @@ -/* - * Copyright (c) Facebook, Inc. and its affiliates. - */ - -import * as React from 'react'; -import {MarkdownPage, MarkdownProps} from './MarkdownPage'; -import {RouteItem} from 'components/Layout/useRouteMeta'; -import {Page} from './Page'; -import sidebarLearn from '../../sidebarLearn.json'; -interface PageFrontmatter { - title: string; -} - -export default function withLearn(meta: PageFrontmatter) { - function LayoutLearn(props: MarkdownProps) { - return ; - } - LayoutLearn.appShell = AppShell; - return LayoutLearn; -} - -function AppShell(props: {children: React.ReactNode}) { - return ; -} diff --git a/beta/src/components/Layout/LayoutPost.tsx b/beta/src/components/Layout/LayoutPost.tsx deleted file mode 100644 index dd1b38049..000000000 --- a/beta/src/components/Layout/LayoutPost.tsx +++ /dev/null @@ -1,117 +0,0 @@ -/* - * Copyright (c) Facebook, Inc. and its affiliates. - */ - -import {MDXProvider} from '@mdx-js/react'; -import recentPostsRouteTree from 'blogIndexRecent.json'; -import {DocsPageFooter} from 'components/DocsFooter'; -import {ExternalLink} from 'components/ExternalLink'; -import {MDXComponents} from 'components/MDX/MDXComponents'; -import {Seo} from 'components/Seo'; -import {Toc} from 'components/Layout/Toc'; -import format from 'date-fns/format'; -import {useRouter} from 'next/router'; -import * as React from 'react'; -import {getAuthor} from 'utils/getAuthor'; -import toCommaSeparatedList from 'utils/toCommaSeparatedList'; -import {Page} from './Page'; -import {RouteItem, useRouteMeta} from './useRouteMeta'; -import {useTwitter} from './useTwitter'; - -interface PageFrontmatter { - id?: string; - title: string; - author: string[]; - date?: string; -} - -interface LayoutPostProps { - /** Sidebar/Nav */ - routes: RouteItem[]; - /** Markdown frontmatter */ - meta: PageFrontmatter; - /** The mdx */ - children: React.ReactNode; -} - -/** Return the date of the current post given the path */ -function getDateFromPath(path: string) { - // All paths are /blog/year/month/day/title - const [year, month, day] = path - .substr(1) // first `/` - .split('/') // make an array - .slice(1) // ignore blog - .map((i) => parseInt(i, 10)); // convert to numbers - - return { - date: format(new Date(year, month, day), 'MMMM dd, yyyy'), - dateTime: [year, month, day].join('-'), - }; -} - -function LayoutPost({meta, children}: LayoutPostProps) { - const {pathname} = useRouter(); - const {date, dateTime} = getDateFromPath(pathname); - const {route, nextRoute, prevRoute} = useRouteMeta(); - const anchors = React.Children.toArray(children) - .filter( - (child: any) => - child.props?.mdxType && ['h2', 'h3'].includes(child.props.mdxType) - ) - .map((child: any) => ({ - url: '#' + child.props.id, - depth: parseInt(child.props.mdxType.replace('h', ''), 0), - text: child.props.children, - })); - useTwitter(); - return ( - <> -
    -
    - -

    - {meta.title} -

    -

    - By{' '} - {toCommaSeparatedList(meta.author, (author) => ( - - {getAuthor(author).name} - - ))} - Β· - - - -

    - - {children} - -
    -
    -
    - -
    - - ); -} - -function AppShell(props: {children: React.ReactNode}) { - return ; -} - -export default function withLayoutPost(meta: any) { - function LayoutPostWrapper(props: LayoutPostProps) { - return ; - } - - LayoutPostWrapper.appShell = AppShell; - - return LayoutPostWrapper; -} diff --git a/beta/src/components/Layout/MarkdownPage.tsx b/beta/src/components/Layout/MarkdownPage.tsx deleted file mode 100644 index 23f640076..000000000 --- a/beta/src/components/Layout/MarkdownPage.tsx +++ /dev/null @@ -1,154 +0,0 @@ -/* - * Copyright (c) Facebook, Inc. and its affiliates. - */ - -import * as React from 'react'; -import {MDXProvider} from '@mdx-js/react'; -import {DocsPageFooter} from 'components/DocsFooter'; -import {MDXComponents} from 'components/MDX/MDXComponents'; -import {Seo} from 'components/Seo'; -import PageHeading from 'components/PageHeading'; -import {useRouteMeta} from './useRouteMeta'; -import {Toc} from './Toc'; -export interface MarkdownProps { - meta: Frontmatter & {description?: string}; - children?: React.ReactNode; -} - -function MaxWidth({children}: {children: any}) { - return
    {children}
    ; -} - -export function MarkdownPage< - T extends {title: string; status?: string} = {title: string; status?: string} ->({children, meta}: MarkdownProps) { - const {route, nextRoute, prevRoute} = useRouteMeta(); - const title = meta.title || route?.title || ''; - const description = meta.description || route?.description || ''; - - let anchors: Array<{ - url: string; - text: React.ReactNode; - depth: number; - }> = React.Children.toArray(children) - .filter((child: any) => { - if (child.props?.mdxType) { - return ['h1', 'h2', 'h3', 'Challenges', 'Recipes', 'Recap'].includes( - child.props.mdxType - ); - } - return false; - }) - .map((child: any) => { - if (child.props.mdxType === 'Challenges') { - return { - url: '#challenges', - depth: 0, - text: '도전', - }; - } - if (child.props.mdxType === 'Recipes') { - return { - url: '#recipes', - depth: 0, - text: 'λ ˆμ‹œν”Ό', - }; - } - if (child.props.mdxType === 'Recap') { - return { - url: '#recap', - depth: 0, - text: 'μš”μ•½', - }; - } - return { - url: '#' + child.props.id, - depth: - (child.props?.mdxType && - parseInt(child.props.mdxType.replace('h', ''), 0)) ?? - 0, - text: child.props.children, - }; - }); - if (anchors.length > 0) { - anchors.unshift({ - depth: 1, - text: 'κ°œμš”', - url: '#', - }); - } - - if (!route) { - console.error('This page was not added to one of the sidebar JSON files.'); - } - const isHomePage = route?.path === '/'; - - // Auto-wrap everything except a few types into - // wrappers. Keep reusing the same - // wrapper as long as we can until we meet - // a full-width section which interrupts it. - let fullWidthTypes = [ - 'Sandpack', - 'APIAnatomy', - 'FullWidth', - 'Illustration', - 'IllustrationBlock', - 'Challenges', - 'Recipes', - ]; - let wrapQueue: React.ReactNode[] = []; - let finalChildren: React.ReactNode[] = []; - function flushWrapper(key: string | number) { - if (wrapQueue.length > 0) { - finalChildren.push({wrapQueue}); - wrapQueue = []; - } - } - function handleChild(child: any, key: string | number) { - if (child == null) { - return; - } - if (typeof child !== 'object') { - wrapQueue.push(child); - return; - } - if (fullWidthTypes.includes(child.props.mdxType)) { - flushWrapper(key); - finalChildren.push(child); - } else { - wrapQueue.push(child); - } - } - React.Children.forEach(children, handleChild); - flushWrapper('last'); - - return ( -
    -
    - - {!isHomePage && ( - - )} -
    -
    - - {finalChildren} - -
    - -
    -
    -
    - {!isHomePage && anchors.length > 0 && } -
    -
    - ); -} diff --git a/beta/src/components/Layout/Nav/MobileNav.tsx b/beta/src/components/Layout/Nav/MobileNav.tsx deleted file mode 100644 index 2b310b43a..000000000 --- a/beta/src/components/Layout/Nav/MobileNav.tsx +++ /dev/null @@ -1,87 +0,0 @@ -/* - * Copyright (c) Facebook, Inc. and its affiliates. - */ - -import * as React from 'react'; -import cn from 'classnames'; -import {RouteItem} from 'components/Layout/useRouteMeta'; -import {useRouter} from 'next/router'; -import {SidebarRouteTree} from '../Sidebar'; -import sidebarHome from '../../../sidebarHome.json'; -import sidebarLearn from '../../../sidebarLearn.json'; -import sidebarReference from '../../../sidebarReference.json'; - -function inferSection(pathname: string): 'learn' | 'reference' | 'home' { - if (pathname.startsWith('/learn')) { - return 'learn'; - } else if (pathname.startsWith('/reference')) { - return 'reference'; - } else { - return 'home'; - } -} - -export function MobileNav() { - const {pathname} = useRouter(); - const [section, setSection] = React.useState(() => inferSection(pathname)); - - let tree = null; - switch (section) { - case 'home': - tree = sidebarHome.routes[0]; - break; - case 'learn': - tree = sidebarLearn.routes[0]; - break; - case 'reference': - tree = sidebarReference.routes[0]; - break; - } - - return ( - <> -
    - setSection('home')}> - Home - - setSection('learn')}> - Learn - - setSection('reference')}> - API - -
    - - - ); -} - -function TabButton({ - children, - onClick, - isActive, -}: { - children: any; - onClick: (event: React.MouseEvent) => void; - isActive: boolean; -}) { - const classes = cn( - 'inline-flex items-center w-full border-b-2 justify-center text-base leading-9 px-3 py-0.5 hover:text-link hover:gray-5', - { - 'text-link dark:text-link-dark dark:border-link-dark border-link font-bold': - isActive, - 'border-transparent': !isActive, - } - ); - return ( - - ); -} diff --git a/beta/src/components/Layout/Nav/Nav.tsx b/beta/src/components/Layout/Nav/Nav.tsx deleted file mode 100644 index 98a130ced..000000000 --- a/beta/src/components/Layout/Nav/Nav.tsx +++ /dev/null @@ -1,206 +0,0 @@ -/* - * Copyright (c) Facebook, Inc. and its affiliates. - */ - -import * as React from 'react'; -import cn from 'classnames'; -import NextLink from 'next/link'; -import {useRouter} from 'next/router'; - -import {IconClose} from 'components/Icon/IconClose'; -import {IconHamburger} from 'components/Icon/IconHamburger'; -import {Search} from 'components/Search'; -import {MenuContext} from 'components/useMenu'; - -import {Logo} from '../../Logo'; -import NavLink from './NavLink'; - -declare global { - interface Window { - __theme: string; - __setPreferredTheme: (theme: string) => void; - } -} - -const feedbackIcon = ( - - - - - - - - - - -); - -const darkIcon = ( - - - - - - -); - -const lightIcon = ( - - - - - - - - - -); - -function inferSection(pathname: string): 'learn' | 'reference' | 'home' { - if (pathname.startsWith('/learn')) { - return 'learn'; - } else if (pathname.startsWith('/reference')) { - return 'reference'; - } else { - return 'home'; - } -} - -export default function Nav() { - const {pathname} = useRouter(); - const {isOpen, toggleOpen} = React.useContext(MenuContext); - const section = inferSection(pathname); - - function handleFeedback() { - const nodes: any = document.querySelectorAll( - '#_hj_feedback_container button' - ); - if (nodes.length > 0) { - nodes[nodes.length - 1].click(); - } else { - window.location.href = - 'https://github.com/reactjs/reactjs.org/issues/3308'; - } - } - - return ( - - ); -} diff --git a/beta/src/components/Layout/Nav/NavLink.tsx b/beta/src/components/Layout/Nav/NavLink.tsx deleted file mode 100644 index 3fddc6e16..000000000 --- a/beta/src/components/Layout/Nav/NavLink.tsx +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Copyright (c) Facebook, Inc. and its affiliates. - */ - -import * as React from 'react'; -import cn from 'classnames'; -import {ExternalLink} from 'components/ExternalLink'; -import NextLink from 'next/link'; - -interface NavLinkProps { - href: string; - children: React.ReactNode; - isActive: boolean; -} - -export default function NavLink({href, children, isActive}: NavLinkProps) { - const classes = cn( - { - 'text-link border-link dark:text-link-dark dark:border-link-dark font-bold': - isActive, - }, - {'border-transparent': !isActive}, - 'inline-flex w-full items-center border-b-2 justify-center text-base leading-9 px-3 py-0.5 hover:text-link dark:hover:text-link-dark whitespace-nowrap' - ); - - if (href.startsWith('https://')) { - return ( - - {children} - - ); - } - - return ( - - {children} - - ); -} diff --git a/beta/src/components/Layout/Nav/index.tsx b/beta/src/components/Layout/Nav/index.tsx deleted file mode 100644 index 0f4d0e78e..000000000 --- a/beta/src/components/Layout/Nav/index.tsx +++ /dev/null @@ -1,5 +0,0 @@ -/* - * Copyright (c) Facebook, Inc. and its affiliates. - */ - -export {default as Nav} from './Nav'; diff --git a/beta/src/components/Layout/Page.tsx b/beta/src/components/Layout/Page.tsx deleted file mode 100644 index 2f8ad2f4d..000000000 --- a/beta/src/components/Layout/Page.tsx +++ /dev/null @@ -1,38 +0,0 @@ -/* - * Copyright (c) Facebook, Inc. and its affiliates. - */ - -import {MenuProvider} from 'components/useMenu'; -import * as React from 'react'; -import {Nav} from './Nav'; -import {RouteItem, SidebarContext} from './useRouteMeta'; -import {Sidebar} from './Sidebar'; -import {Footer} from './Footer'; -interface PageProps { - children: React.ReactNode; - routeTree: RouteItem; -} - -export function Page({routeTree, children}: PageProps) { - return ( - - -
    -
    -
    - -
    -
    -
    - {children} -
    -
    -
    -
    -
    -
    -
    - ); -} diff --git a/beta/src/components/Layout/Sidebar/Sidebar.tsx b/beta/src/components/Layout/Sidebar/Sidebar.tsx deleted file mode 100644 index 0b03a73a6..000000000 --- a/beta/src/components/Layout/Sidebar/Sidebar.tsx +++ /dev/null @@ -1,92 +0,0 @@ -/* - * Copyright (c) Facebook, Inc. and its affiliates. - */ - -import * as React from 'react'; -import cn from 'classnames'; -import {SidebarContext} from 'components/Layout/useRouteMeta'; -import {MenuContext} from 'components/useMenu'; -import {useMediaQuery} from '../useMediaQuery'; -import {SidebarRouteTree} from './SidebarRouteTree'; -import {Search} from 'components/Search'; -import {Button} from 'components/Button'; -import {MobileNav} from '../Nav/MobileNav'; - -const SIDEBAR_BREAKPOINT = 1023; - -export function Sidebar({isMobileOnly}: {isMobileOnly?: boolean}) { - const {menuRef, isOpen} = React.useContext(MenuContext); - const isMobileSidebar = useMediaQuery(SIDEBAR_BREAKPOINT); - let routeTree = React.useContext(SidebarContext); - const isHidden = isMobileSidebar ? !isOpen : false; - - // HACK. Fix up the data structures instead. - if ((routeTree as any).routes.length === 1) { - routeTree = (routeTree as any).routes[0]; - } - - function handleFeedback() { - const nodes: any = document.querySelectorAll( - '#_hj_feedback_container button' - ); - if (nodes.length > 0) { - nodes[nodes.length - 1].click(); - } else { - window.location.href = - 'https://github.com/reactjs/reactjs.org/issues/3308'; - } - } - const feedbackIcon = ( - - - - - - - - - - - ); - return ( - - ); -} diff --git a/beta/src/components/Layout/Sidebar/SidebarLink.tsx b/beta/src/components/Layout/Sidebar/SidebarLink.tsx deleted file mode 100644 index 72383a556..000000000 --- a/beta/src/components/Layout/Sidebar/SidebarLink.tsx +++ /dev/null @@ -1,85 +0,0 @@ -/* - * Copyright (c) Facebook, Inc. and its affiliates. - */ - -/* eslint-disable jsx-a11y/no-static-element-interactions */ -/* eslint-disable jsx-a11y/click-events-have-key-events */ -import * as React from 'react'; -import scrollIntoView from 'scroll-into-view-if-needed'; -import cn from 'classnames'; -import {IconNavArrow} from 'components/Icon/IconNavArrow'; -import Link from 'next/link'; -import {useIsMobile} from '../useMediaQuery'; - -interface SidebarLinkProps { - href: string; - selected?: boolean; - title: string; - level: number; - icon?: React.ReactNode; - heading?: boolean; - isExpanded?: boolean; - isBreadcrumb?: boolean; - hideArrow?: boolean; -} - -export function SidebarLink({ - href, - selected = false, - title, - level, - heading = false, - isExpanded, - isBreadcrumb, - hideArrow, -}: SidebarLinkProps) { - const ref = React.useRef(null); - const isMobile = useIsMobile(); - - React.useEffect(() => { - if (ref && ref.current && !!selected && !isMobile) { - scrollIntoView(ref.current, { - scrollMode: 'if-needed', - block: 'center', - inline: 'nearest', - }); - } - }, [ref, selected, isMobile]); - - return ( - - 0, - 'pl-5': level < 2, - 'text-base font-bold': level === 0, - 'dark:text-primary-dark text-primary ': level === 0 && !selected, - 'text-base text-link dark:text-link-dark': level === 1 && selected, - 'dark:text-primary-dark text-primary': heading, - 'text-base text-secondary dark:text-secondary-dark': - !selected && !heading, - 'text-base text-link dark:text-link-dark bg-highlight dark:bg-highlight-dark border-blue-40 hover:bg-highlight hover:text-link dark:hover:bg-highlight-dark dark:hover:text-link-dark': - selected, - } - )}> - {title} - {isExpanded != null && !heading && !hideArrow && ( - - - - )} - - - ); -} diff --git a/beta/src/components/Layout/Sidebar/SidebarRouteTree.tsx b/beta/src/components/Layout/Sidebar/SidebarRouteTree.tsx deleted file mode 100644 index 0ebb4615b..000000000 --- a/beta/src/components/Layout/Sidebar/SidebarRouteTree.tsx +++ /dev/null @@ -1,156 +0,0 @@ -/* - * Copyright (c) Facebook, Inc. and its affiliates. - */ - -import * as React from 'react'; -import cn from 'classnames'; -import {RouteItem} from 'components/Layout/useRouteMeta'; -import {useRouter} from 'next/router'; -import {removeFromLast} from 'utils/removeFromLast'; -import {useRouteMeta} from '../useRouteMeta'; -import {SidebarLink} from './SidebarLink'; -import useCollapse from 'react-collapsed'; -import {useLayoutEffect} from 'react'; - -interface SidebarRouteTreeProps { - isMobile?: boolean; - routeTree: RouteItem; - level?: number; -} - -function CollapseWrapper({ - isExpanded, - duration, - children, -}: { - isExpanded: boolean; - duration: number; - children: any; -}) { - const ref = React.useRef(null); - const timeoutRef = React.useRef(null); - const {getCollapseProps} = useCollapse({ - isExpanded, - duration, - }); - - // Disable pointer events while animating. - const isExpandedRef = React.useRef(isExpanded); - if (typeof window !== 'undefined') { - // eslint-disable-next-line react-hooks/rules-of-hooks - useLayoutEffect(() => { - const wasExpanded = isExpandedRef.current; - if (wasExpanded === isExpanded) { - return; - } - isExpandedRef.current = isExpanded; - if (ref.current !== null) { - const node: HTMLDivElement = ref.current; - node.style.pointerEvents = 'none'; - if (timeoutRef.current !== null) { - window.clearTimeout(timeoutRef.current); - } - timeoutRef.current = window.setTimeout(() => { - node.style.pointerEvents = ''; - }, duration + 100); - } - }); - } - - return ( -
    -
    {children}
    -
    - ); -} - -export function SidebarRouteTree({ - isMobile, - routeTree, - level = 0, -}: SidebarRouteTreeProps) { - const {breadcrumbs} = useRouteMeta(routeTree); - const {pathname} = useRouter(); - const slug = pathname; - - const currentRoutes = routeTree.routes as RouteItem[]; - const expandedPath = currentRoutes.reduce( - (acc: string | undefined, curr: RouteItem) => { - if (acc) return acc; - const breadcrumb = breadcrumbs.find((b) => b.path === curr.path); - if (breadcrumb) { - return curr.path; - } - if (curr.path === pathname) { - return pathname; - } - return undefined; - }, - undefined - ); - - const expanded = expandedPath; - return ( -
      - {currentRoutes.map(({path, title, routes, heading}) => { - const pagePath = path && removeFromLast(path, '.'); - const selected = slug === pagePath; - - // if current route item has no path and children treat it as an API sidebar heading - if (!path || !pagePath || heading) { - return ( - - ); - } - - // if route has a path and child routes, treat it as an expandable sidebar item - if (routes) { - const isExpanded = isMobile || expanded === path; - return ( -
    • - - - - -
    • - ); - } - - // if route has a path and no child routes, treat it as a sidebar link - return ( -
    • - -
    • - ); - })} -
    - ); -} diff --git a/beta/src/components/Layout/Sidebar/index.tsx b/beta/src/components/Layout/Sidebar/index.tsx deleted file mode 100644 index a2204a508..000000000 --- a/beta/src/components/Layout/Sidebar/index.tsx +++ /dev/null @@ -1,8 +0,0 @@ -/* - * Copyright (c) Facebook, Inc. and its affiliates. - */ - -export {Sidebar} from './Sidebar'; -export {SidebarButton} from './SidebarButton'; -export {SidebarLink} from './SidebarLink'; -export {SidebarRouteTree} from './SidebarRouteTree'; diff --git a/beta/src/components/Layout/Toc.tsx b/beta/src/components/Layout/Toc.tsx deleted file mode 100644 index c21810df6..000000000 --- a/beta/src/components/Layout/Toc.tsx +++ /dev/null @@ -1,81 +0,0 @@ -/* - * Copyright (c) Facebook, Inc. and its affiliates. - */ - -import cx from 'classnames'; -import * as React from 'react'; -import {useTocHighlight} from './useTocHighlight'; - -export function Toc({ - headings, -}: { - headings: Array<{url: string; text: React.ReactNode; depth: number}>; -}) { - const {currentIndex} = useTocHighlight(); - // TODO: We currently have a mismatch between the headings in the document - // and the headings we find in MarkdownPage (i.e. we don't find Recap or Challenges). - // Select the max TOC item we have here for now, but remove this after the fix. - const selectedIndex = Math.min(currentIndex, headings.length - 1); - return ( - - ); -} diff --git a/beta/src/components/Layout/useMediaQuery.tsx b/beta/src/components/Layout/useMediaQuery.tsx deleted file mode 100644 index 3d541bd70..000000000 --- a/beta/src/components/Layout/useMediaQuery.tsx +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Copyright (c) Facebook, Inc. and its affiliates. - */ - -import {useState, useCallback, useEffect} from 'react'; - -const useMediaQuery = (width: number) => { - const [targetReached, setTargetReached] = useState(false); - - const updateTarget = useCallback((e) => { - if (e.matches) { - setTargetReached(true); - } else { - setTargetReached(false); - } - }, []); - - useEffect(() => { - const media = window.matchMedia(`(max-width: ${width}px)`); - media.addEventListener('change', updateTarget); - - // Check on mount (callback is not called until a change occurs) - if (media.matches) { - setTargetReached(true); - } - - return () => media.removeEventListener('change', updateTarget); - }, [updateTarget, width]); - - return targetReached; -}; - -const useIsMobile = () => { - return useMediaQuery(640); -}; - -export {useMediaQuery, useIsMobile}; diff --git a/beta/src/components/Layout/useRouteMeta.tsx b/beta/src/components/Layout/useRouteMeta.tsx deleted file mode 100644 index 5f962f7ea..000000000 --- a/beta/src/components/Layout/useRouteMeta.tsx +++ /dev/null @@ -1,129 +0,0 @@ -/* - * Copyright (c) Facebook, Inc. and its affiliates. - */ - -import * as React from 'react'; -import {useRouter} from 'next/router'; - -/** - * While Next.js provides file-based routing, we still need to construct - * a sidebar for navigation and provide each markdown page - * previous/next links and titles. To do this, we construct a nested - * route object that is infinitely nestable. - */ - -export type RouteTag = - | 'foundation' - | 'intermediate' - | 'advanced' - | 'experimental' - | 'deprecated'; - -export interface RouteItem { - /** Page title (for the sidebar) */ - title: string; - /** Optional page description for heading */ - description?: string; - /* Additional meta info for page tagging */ - tags?: RouteTag[]; - /** Path to page */ - path?: string; - /** Whether the entry is a heading */ - heading?: boolean; - /** List of sub-routes */ - routes?: RouteItem[]; -} - -export interface Routes { - /** List of routes */ - routes: RouteItem[]; -} - -/** Routing metadata about a given route and it's siblings and parent */ -export interface RouteMeta { - /** The previous route */ - prevRoute?: RouteItem; - /** The next route */ - nextRoute?: RouteItem; - /** The current route */ - route?: RouteItem; - /** Trail of parent routes */ - breadcrumbs?: RouteItem[]; -} - -export function useRouteMeta(rootRoute?: RouteItem) { - const sidebarContext = React.useContext(SidebarContext); - const routeTree = rootRoute || sidebarContext; - const router = useRouter(); - const cleanedPath = router.pathname; - if (cleanedPath === '/404') { - return { - breadcrumbs: [], - }; - } - const breadcrumbs = getBreadcrumbs(cleanedPath, routeTree); - return { - ...getRouteMeta(cleanedPath, routeTree), - breadcrumbs: breadcrumbs.length > 0 ? breadcrumbs : [routeTree], - }; -} - -export const SidebarContext = React.createContext({title: 'root'}); - -// Performs a depth-first search to find the current route and its previous/next route -function getRouteMeta( - searchPath: string, - currentRoute: RouteItem, - ctx: RouteMeta = {} -): RouteMeta { - const {routes} = currentRoute; - - if (ctx.route && !ctx.nextRoute) { - ctx.nextRoute = currentRoute; - } - - if (currentRoute.path === searchPath) { - ctx.route = currentRoute; - } - - if (!ctx.route) { - ctx.prevRoute = currentRoute; - } - - if (!routes) { - return ctx; - } - - for (const route of routes) { - getRouteMeta(searchPath, route, ctx); - } - - return ctx; -} - -// iterates the route tree from the current route to find its ancestors for breadcrumbs -function getBreadcrumbs( - path: string, - currentRoute: RouteItem, - breadcrumbs: RouteItem[] = [] -): RouteItem[] { - if (currentRoute.path === path) { - return breadcrumbs; - } - - if (!currentRoute.routes) { - return []; - } - - for (const route of currentRoute.routes) { - const childRoute = getBreadcrumbs(path, route, [ - ...breadcrumbs, - currentRoute, - ]); - if (childRoute?.length) { - return childRoute; - } - } - - return []; -} diff --git a/beta/src/components/Layout/useTwitter.tsx b/beta/src/components/Layout/useTwitter.tsx deleted file mode 100644 index ee76a6a5c..000000000 --- a/beta/src/components/Layout/useTwitter.tsx +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Copyright (c) Facebook, Inc. and its affiliates. - */ - -/** - * Ported from gatsby-plugin-twitter - * https://github.com/gatsbyjs/gatsby/tree/master/packages/gatsby-plugin-twitter - */ -import * as React from 'react'; - -const injectTwitterScript = function injectTwitterScript() { - function addJS(jsCode: any) { - const s = document.createElement('script'); - s.type = 'text/javascript'; - s.innerText = jsCode; - document.getElementsByTagName('head')[0].appendChild(s); - } - - addJS( - '\n window.twttr = (function(d, s, id) {\n var js,\n fjs = d.getElementsByTagName(s)[0],\n t = window.twttr || {};\n if (d.getElementById(id)) return t;\n js = d.createElement(s);\n js.id = id;\n js.src = "https://platform.twitter.com/widgets.js";\n fjs.parentNode.insertBefore(js, fjs);\n t._e = [];\n t.ready = function(f) {\n t._e.push(f);\n };\n return t;\n })(document, "script", "twitter-wjs");\n ' - ); -}; - -let injectedTwitterScript = false; -const embedClasses = [ - '.twitter-tweet', - '.twitter-timeline', - '.twitter-follow-button', - '.twitter-share-button', -].join(','); - -export function useTwitter() { - React.useEffect(() => { - if (document.querySelector(embedClasses) !== null) { - if (!injectedTwitterScript) { - injectTwitterScript(); - injectedTwitterScript = true; - } - - if ( - typeof (window as any).twttr !== 'undefined' && - (window as any).twttr.widgets && - typeof (window as any).twttr.widgets.load === 'function' - ) { - (window as any).twttr.widgets.load(); - } - } - }, []); -} diff --git a/beta/src/components/Logo.tsx b/beta/src/components/Logo.tsx deleted file mode 100644 index 0efa7acc1..000000000 --- a/beta/src/components/Logo.tsx +++ /dev/null @@ -1,28 +0,0 @@ -/* - * Copyright (c) Facebook, Inc. and its affiliates. - */ - -import * as React from 'react'; - -export function Logo(props: JSX.IntrinsicElements['svg']) { - return ( - - - - - ); -} - -Logo.displayName = 'Logo'; diff --git a/beta/src/components/MDX/APIAnatomy.tsx b/beta/src/components/MDX/APIAnatomy.tsx deleted file mode 100644 index 452a91dcd..000000000 --- a/beta/src/components/MDX/APIAnatomy.tsx +++ /dev/null @@ -1,119 +0,0 @@ -/* - * Copyright (c) Facebook, Inc. and its affiliates. - */ - -import * as React from 'react'; -import cn from 'classnames'; -import tailwindConfig from '../../../tailwind.config'; -import CodeBlock from './CodeBlock'; - -interface APIAnatomyProps { - children: React.ReactNode; -} - -interface AnatomyContent { - steps: React.ReactElement[]; - code: React.ReactNode; -} - -const twColors = tailwindConfig.theme.extend.colors; -const colors = [ - { - hex: twColors['blue-40'], - border: 'border-blue-40', - background: 'bg-blue-40', - }, - { - hex: twColors['yellow-40'], - border: 'border-yellow-40', - background: 'bg-yellow-40', - }, - { - hex: twColors['green-50'], - border: 'border-green-50', - background: 'bg-green-50', - }, - { - hex: twColors['purple-40'], - border: 'border-purple-40', - background: 'bg-purple-40', - }, -]; - -export function APIAnatomy({children}: APIAnatomyProps) { - const [activeStep, setActiveStep] = React.useState(null); - - const {steps, code} = React.Children.toArray(children).reduce( - (acc: AnatomyContent, child) => { - if (!React.isValidElement(child)) return acc; - switch (child.props.mdxType) { - case 'AnatomyStep': - acc.steps.push( - React.cloneElement(child, { - ...child.props, - activeStep, - handleStepChange: setActiveStep, - stepNumber: acc.steps.length + 1, - }) - ); - break; - case 'pre': - acc.code = ( - - ); - break; - } - return acc; - }, - {steps: [], code: null} - ); - - return ( -
    -
    {code}
    -
    - {steps} -
    -
    - ); -} - -interface AnatomyStepProps { - children: React.ReactNode; - title: string; - stepNumber: number; - activeStep?: number; - handleStepChange: (stepNumber: number) => void; -} - -export function AnatomyStep({ - title, - stepNumber, - children, - activeStep, - handleStepChange, -}: AnatomyStepProps) { - const color = colors[stepNumber - 1]; - return ( -
    -
    -
    - {stepNumber} -
    -
    - {title} -
    -
    -
    {children}
    -
    - ); -} diff --git a/beta/src/components/MDX/Challenges/Challenges.tsx b/beta/src/components/MDX/Challenges/Challenges.tsx deleted file mode 100644 index d7934674b..000000000 --- a/beta/src/components/MDX/Challenges/Challenges.tsx +++ /dev/null @@ -1,234 +0,0 @@ -/* - * Copyright (c) Facebook, Inc. and its affiliates. - */ - -import * as React from 'react'; -import cn from 'classnames'; -import {Button} from 'components/Button'; -import {H2} from 'components/MDX/Heading'; -import {Navigation} from './Navigation'; -import {IconHint} from '../../Icon/IconHint'; -import {IconSolution} from '../../Icon/IconSolution'; -import {IconArrowSmall} from '../../Icon/IconArrowSmall'; - -interface ChallengesProps { - children: React.ReactElement[]; - isRecipes?: boolean; -} - -export interface ChallengeContents { - id: string; - name: string; - order: number; - content: React.ReactNode; - solution: React.ReactNode; - hint?: React.ReactNode; -} - -const parseChallengeContents = ( - children: React.ReactElement[] -): ChallengeContents[] => { - const contents: ChallengeContents[] = []; - - if (!children) { - return contents; - } - - let challenge: Partial = {}; - let content: React.ReactElement[] = []; - React.Children.forEach(children, (child) => { - const {props} = child; - switch (props.mdxType) { - case 'Solution': { - challenge.solution = child; - challenge.content = content; - contents.push(challenge as ChallengeContents); - challenge = {}; - content = []; - break; - } - case 'Hint': { - challenge.hint = child; - break; - } - case 'h3': { - challenge.order = contents.length + 1; - challenge.name = props.children; - challenge.id = props.id; - break; - } - default: { - content.push(child); - } - } - }); - - return contents; -}; - -export function Challenges({children, isRecipes}: ChallengesProps) { - const challenges = parseChallengeContents(children); - const scrollAnchorRef = React.useRef(null); - - const [showHint, setShowHint] = React.useState(false); - const [showSolution, setShowSolution] = React.useState(false); - const [activeChallenge, setActiveChallenge] = React.useState( - challenges[0].id - ); - - const handleChallengeChange = (challengeId: string) => { - setShowHint(false); - setShowSolution(false); - setActiveChallenge(challengeId); - }; - - const toggleHint = () => { - if (showSolution && !showHint) { - setShowSolution(false); - } - setShowHint((hint) => !hint); - }; - - const toggleSolution = () => { - if (showHint && !showSolution) { - setShowHint(false); - } - setShowSolution((solution) => !solution); - }; - - const currentChallenge = challenges.find(({id}) => id === activeChallenge); - if (currentChallenge === undefined) { - throw new TypeError('currentChallenge should always exist'); - } - const nextChallenge = challenges.find(({order}) => { - return order === currentChallenge.order + 1; - }); - - return ( -
    -
    -
    -

    - {isRecipes - ? 'λͺ‡ κ°€μ§€ λ ˆμ‹œν”Όλ₯Ό μ‹œλ„ν•΄ λ³΄μ„Έμš”.' - : 'λͺ‡ κ°€μ§€ 도전을 μ‹œλ„ν•΄ λ³΄μ„Έμš”.'} -

    - {challenges.length > 1 && ( - - )} -
    -
    -
    -

    -
    - {isRecipes ? 'Recipe' : 'Challenge'} {currentChallenge.order} of{' '} - {challenges.length} - : -
    - {currentChallenge.name} -

    - <>{currentChallenge.content} -
    -
    - {currentChallenge.hint ? ( -
    - - -
    - ) : ( - !isRecipes && ( - - ) - )} - - {nextChallenge && ( - - )} -
    - {showHint && currentChallenge.hint} - - {showSolution && ( -
    -

    - ν•΄κ²°μ±… -

    - {currentChallenge.solution} -
    - - {nextChallenge && ( - - )} -
    -
    - )} -
    -
    -
    - ); -} diff --git a/beta/src/components/MDX/Challenges/Navigation.tsx b/beta/src/components/MDX/Challenges/Navigation.tsx deleted file mode 100644 index 6f82b1bc8..000000000 --- a/beta/src/components/MDX/Challenges/Navigation.tsx +++ /dev/null @@ -1,134 +0,0 @@ -/* - * Copyright (c) Facebook, Inc. and its affiliates. - */ - -import React, {createRef} from 'react'; -import cn from 'classnames'; -import {IconChevron} from 'components/Icon/IconChevron'; -import {ChallengeContents} from './Challenges'; -const debounce = require('debounce'); - -export function Navigation({ - challenges, - handleChange, - currentChallenge, - isRecipes, -}: { - challenges: ChallengeContents[]; - handleChange: (id: string) => void; - currentChallenge: ChallengeContents; - isRecipes?: boolean; -}) { - const containerRef = React.useRef(null); - const challengesNavRef = React.useRef( - challenges.map(() => createRef()) - ); - const scrollPos = currentChallenge.order - 1; - const canScrollLeft = scrollPos > 0; - const canScrollRight = scrollPos < challenges.length - 1; - - const handleScrollRight = () => { - if (scrollPos < challenges.length - 1) { - const currentNavRef = challengesNavRef.current[scrollPos + 1].current; - if (!currentNavRef) { - return; - } - if (containerRef.current) { - containerRef.current.scrollLeft = currentNavRef.offsetLeft; - } - handleChange(challenges[scrollPos + 1].id); - } - }; - - const handleScrollLeft = () => { - if (scrollPos > 0) { - const currentNavRef = challengesNavRef.current[scrollPos - 1].current; - if (!currentNavRef) { - return; - } - if (containerRef.current) { - containerRef.current.scrollLeft = currentNavRef.offsetLeft; - } - handleChange(challenges[scrollPos - 1].id); - } - }; - - const handleSelectNav = (id: string) => { - const selectedChallenge = challenges.findIndex( - (challenge) => challenge.id === id - ); - const currentNavRef = challengesNavRef.current[selectedChallenge].current; - if (containerRef.current) { - containerRef.current.scrollLeft = currentNavRef?.offsetLeft || 0; - } - handleChange(id); - }; - - const handleResize = React.useCallback(() => { - if (containerRef.current) { - const el = containerRef.current; - el.scrollLeft = - challengesNavRef.current[scrollPos].current?.offsetLeft || 0; - } - }, [containerRef, challengesNavRef, scrollPos]); - - React.useEffect(() => { - handleResize(); - window.addEventListener('resize', debounce(handleResize, 200)); - return () => { - window.removeEventListener('resize', handleResize); - }; - }, [handleResize]); - - return ( -
    -
    -
    - {challenges.map(({name, id, order}, index) => ( - - ))} -
    -
    -
    - - -
    -
    - ); -} diff --git a/beta/src/components/MDX/Challenges/index.tsx b/beta/src/components/MDX/Challenges/index.tsx deleted file mode 100644 index b39b2f223..000000000 --- a/beta/src/components/MDX/Challenges/index.tsx +++ /dev/null @@ -1,14 +0,0 @@ -/* - * Copyright (c) Facebook, Inc. and its affiliates. - */ - -import React from 'react'; -export {Challenges} from './Challenges'; - -export function Hint({children}: {children: React.ReactNode}) { - return
    {children}
    ; -} - -export function Solution({children}: {children: React.ReactNode}) { - return
    {children}
    ; -} diff --git a/beta/src/components/MDX/CodeBlock/CodeBlock.module.css b/beta/src/components/MDX/CodeBlock/CodeBlock.module.css deleted file mode 100644 index 176c53e50..000000000 --- a/beta/src/components/MDX/CodeBlock/CodeBlock.module.css +++ /dev/null @@ -1,7 +0,0 @@ -/* - * Copyright (c) Facebook, Inc. and its affiliates. - */ - -.codeViewer { - padding: 6px 0.5rem !important; -} diff --git a/beta/src/components/MDX/CodeBlock/CodeBlock.tsx b/beta/src/components/MDX/CodeBlock/CodeBlock.tsx deleted file mode 100644 index e36cb1d90..000000000 --- a/beta/src/components/MDX/CodeBlock/CodeBlock.tsx +++ /dev/null @@ -1,171 +0,0 @@ -/* - * Copyright (c) Facebook, Inc. and its affiliates. - */ - -import cn from 'classnames'; -import { - ClasserProvider, - SandpackCodeViewer, - SandpackProvider, - SandpackThemeProvider, -} from '@codesandbox/sandpack-react'; -import rangeParser from 'parse-numeric-range'; -import {CustomTheme} from '../Sandpack/Themes'; -import styles from './CodeBlock.module.css'; - -interface InlineHiglight { - step: number; - line: number; - startColumn: number; - endColumn: number; -} - -const CodeBlock = function CodeBlock({ - children, - className = 'language-js', - metastring, - noMargin, - noMarkers, -}: { - children: string; - className?: string; - metastring: string; - noMargin?: boolean; - noMarkers?: boolean; -}) { - const getDecoratedLineInfo = () => { - if (!metastring) { - return []; - } - - const linesToHighlight = getHighlightLines(metastring); - const highlightedLineConfig = linesToHighlight.map((line) => { - return { - className: 'bg-github-highlight dark:bg-opacity-10', - line, - }; - }); - - const inlineHighlightLines = getInlineHighlights(metastring, children); - const inlineHighlightConfig = inlineHighlightLines.map( - (line: InlineHiglight) => ({ - ...line, - elementAttributes: {'data-step': `${line.step}`}, - className: cn('code-step bg-opacity-10 relative rounded-md p-1 ml-2', { - 'pl-3 before:content-[attr(data-step)] before:block before:w-4 before:h-4 before:absolute before:top-1 before:-left-2 before:rounded-full before:text-white before:text-center before:text-xs before:leading-4': - !noMarkers, - 'bg-blue-40 before:bg-blue-40': line.step === 1, - 'bg-yellow-40 before:bg-yellow-40': line.step === 2, - 'bg-green-40 before:bg-green-40': line.step === 3, - 'bg-purple-40 before:bg-purple-40': line.step === 4, - }), - }) - ); - - return highlightedLineConfig.concat(inlineHighlightConfig); - }; - - // e.g. "language-js" - const language = className.substring(9); - const filename = '/index.' + language; - const decorators = getDecoratedLineInfo(); - return ( -
    - - - - - - - -
    - ); -}; - -export default CodeBlock; - -/** - * - * @param metastring string provided after the language in a markdown block - * @returns array of lines to highlight - * @example - * ```js {1-3,7} [[1, 1, 20, 33], [2, 4, 4, 8]] App.js active - * ... - * ``` - * - * -> The metastring is `{1-3,7} [[1, 1, 20, 33], [2, 4, 4, 8]] App.js active` - */ -function getHighlightLines(metastring: string): number[] { - const HIGHLIGHT_REGEX = /{([\d,-]+)}/; - const parsedMetastring = HIGHLIGHT_REGEX.exec(metastring); - if (!parsedMetastring) { - return []; - } - return rangeParser(parsedMetastring[1]); -} - -/** - * - * @param metastring string provided after the language in a markdown block - * @returns InlineHighlight[] - * @example - * ```js {1-3,7} [[1, 1, 'count'], [2, 4, 'setCount']] App.js active - * ... - * ``` - * - * -> The metastring is `{1-3,7} [[1, 1, 'count', [2, 4, 'setCount']] App.js active` - */ -function getInlineHighlights(metastring: string, code: string) { - const INLINE_HIGHT_REGEX = /(\[\[.*\]\])/; - const parsedMetastring = INLINE_HIGHT_REGEX.exec(metastring); - if (!parsedMetastring) { - return []; - } - - const lines = code.split('\n'); - const encodedHiglights = JSON.parse(parsedMetastring[1]); - return encodedHiglights.map(([step, lineNo, substr, fromIndex]: any[]) => { - const line = lines[lineNo - 1]; - let index = line.indexOf(substr); - const lastIndex = line.lastIndexOf(substr); - if (index !== lastIndex) { - if (fromIndex === undefined) { - throw Error( - "Found '" + - substr + - "' twice. Specify fromIndex as the fourth value in the tuple." - ); - } - index = line.indexOf(substr, fromIndex); - } - if (index === -1) { - throw Error("Could not find: '" + substr + "'"); - } - return { - step, - line: lineNo, - startColumn: index, - endColumn: index + substr.length, - }; - }); -} diff --git a/beta/src/components/MDX/CodeBlock/index.tsx b/beta/src/components/MDX/CodeBlock/index.tsx deleted file mode 100644 index 12c2da981..000000000 --- a/beta/src/components/MDX/CodeBlock/index.tsx +++ /dev/null @@ -1,7 +0,0 @@ -/* - * Copyright (c) Facebook, Inc. and its affiliates. - */ - -import CodeBlock from './CodeBlock'; - -export default CodeBlock; diff --git a/beta/src/components/MDX/CodeDiagram.tsx b/beta/src/components/MDX/CodeDiagram.tsx deleted file mode 100644 index d6ad640d1..000000000 --- a/beta/src/components/MDX/CodeDiagram.tsx +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Copyright (c) Facebook, Inc. and its affiliates. - */ - -import * as React from 'react'; -import CodeBlock from './CodeBlock'; - -interface CodeDiagramProps { - children: React.ReactNode; - flip?: boolean; -} - -export function CodeDiagram({children, flip = false}: CodeDiagramProps) { - const illustration = React.Children.toArray(children).filter((child: any) => { - return child.props?.mdxType === 'img'; - }); - const content = React.Children.toArray(children).map((child: any) => { - if (child.props?.mdxType === 'pre') { - return ( - - ); - } else if (child.props?.mdxType === 'img') { - return null; - } else { - return child; - } - }); - if (flip) { - return ( -
    - {illustration} -
    {content}
    -
    - ); - } - return ( -
    -
    {content}
    -
    {illustration}
    -
    - ); -} diff --git a/beta/src/components/MDX/ConsoleBlock.tsx b/beta/src/components/MDX/ConsoleBlock.tsx deleted file mode 100644 index 9195cdaca..000000000 --- a/beta/src/components/MDX/ConsoleBlock.tsx +++ /dev/null @@ -1,78 +0,0 @@ -/* - * Copyright (c) Facebook, Inc. and its affiliates. - */ - -import * as React from 'react'; -import cn from 'classnames'; -import {IconWarning} from '../Icon/IconWarning'; -import {IconError} from '../Icon/IconError'; - -type LogLevel = 'info' | 'warning' | 'error'; - -interface ConsoleBlockProps { - level?: LogLevel; - children: React.ReactNode; -} - -const Box = ({ - width = '60px', - height = '17px', - className, - customStyles, -}: { - width?: string; - height?: string; - className?: string; - customStyles?: Record; -}) => ( -
    -); -Box.displayName = 'Box'; - -function ConsoleBlock({level = 'info', children}: ConsoleBlockProps) { - let message: string | undefined; - if (typeof children === 'string') { - message = children; - } else if ( - React.isValidElement(children) && - typeof children.props.children === 'string' - ) { - message = children.props.children; - } - - return ( -
    -
    -
    - -
    -
    -
    - Console -
    -
    - - - -
    -
    -
    -
    - {level === 'error' && } - {level === 'warning' && } -
    {message}
    -
    -
    - ); -} - -export default ConsoleBlock; diff --git a/beta/src/components/MDX/Convention.tsx b/beta/src/components/MDX/Convention.tsx deleted file mode 100644 index 434053aac..000000000 --- a/beta/src/components/MDX/Convention.tsx +++ /dev/null @@ -1,25 +0,0 @@ -/* - * Copyright (c) Facebook, Inc. and its affiliates. - */ - -import * as React from 'react'; -import {H3} from './Heading'; - -interface ConventionProps { - children: React.ReactNode; - name: string; -} - -function Convention({children, name}: ConventionProps) { - const id = name ? `${name}-conventions` : 'conventions'; - return ( -
    -

    - Conventions -

    - {children} -
    - ); -} - -export default Convention; diff --git a/beta/src/components/MDX/ExpandableCallout.tsx b/beta/src/components/MDX/ExpandableCallout.tsx deleted file mode 100644 index bae14a083..000000000 --- a/beta/src/components/MDX/ExpandableCallout.tsx +++ /dev/null @@ -1,66 +0,0 @@ -/* - * Copyright (c) Facebook, Inc. and its affiliates. - */ - -import * as React from 'react'; -import cn from 'classnames'; -import {IconNote} from '../Icon/IconNote'; -import {IconGotcha} from '../Icon/IconGotcha'; - -type CalloutVariants = 'gotcha' | 'note'; - -interface ExpandableCalloutProps { - children: React.ReactNode; - type: CalloutVariants; -} - -const variantMap = { - note: { - title: '주의', - Icon: IconNote, - containerClasses: - 'bg-green-5 dark:bg-green-60 dark:bg-opacity-20 text-primary dark:text-primary-dark text-lg', - textColor: 'text-green-60 dark:text-green-40', - overlayGradient: - 'linear-gradient(rgba(245, 249, 248, 0), rgba(245, 249, 248, 1)', - }, - gotcha: { - title: 'μ•Œκ² λ‹€!', - Icon: IconGotcha, - containerClasses: 'bg-yellow-5 dark:bg-yellow-60 dark:bg-opacity-20', - textColor: 'text-yellow-50 dark:text-yellow-40', - overlayGradient: - 'linear-gradient(rgba(249, 247, 243, 0), rgba(249, 247, 243, 1)', - }, -}; - -function ExpandableCallout({children, type}: ExpandableCalloutProps) { - const contentRef = React.useRef(null); - const variant = variantMap[type]; - - return ( -
    -

    - - {variant.title} -

    -
    -
    - {children} -
    -
    -
    - ); -} - -ExpandableCallout.defaultProps = { - type: 'note', -}; - -export default ExpandableCallout; diff --git a/beta/src/components/MDX/ExpandableExample.tsx b/beta/src/components/MDX/ExpandableExample.tsx deleted file mode 100644 index e760c1f01..000000000 --- a/beta/src/components/MDX/ExpandableExample.tsx +++ /dev/null @@ -1,87 +0,0 @@ -/* - * Copyright (c) Facebook, Inc. and its affiliates. - */ - -import * as React from 'react'; -import cn from 'classnames'; -import {IconChevron} from '../Icon/IconChevron'; -import {IconDeepDive} from '../Icon/IconDeepDive'; -import {IconCodeBlock} from '../Icon/IconCodeBlock'; -import {Button} from '../Button'; - -interface ExpandableExampleProps { - children: React.ReactNode; - title: string; - excerpt?: string; - type: 'DeepDive' | 'Example'; -} - -function ExpandableExample({ - children, - title, - excerpt, - type, -}: ExpandableExampleProps) { - const [isExpanded, setIsExpanded] = React.useState(false); - const isDeepDive = type === 'DeepDive'; - const isExample = type === 'Example'; - - return ( -
    -
    -
    - {isDeepDive && ( - <> - - 깊게 λΆ„μ„ν•˜κΈ° - - )} - {isExample && ( - <> - - μ˜ˆμ‹œ - - )} -
    -
    -

    - {title} -

    - {excerpt &&
    {excerpt}
    } -
    - -
    -
    - {children} -
    -
    - ); -} - -export default ExpandableExample; diff --git a/beta/src/components/MDX/Heading.tsx b/beta/src/components/MDX/Heading.tsx deleted file mode 100644 index 664ac6eaf..000000000 --- a/beta/src/components/MDX/Heading.tsx +++ /dev/null @@ -1,128 +0,0 @@ -/* - * Copyright (c) Facebook, Inc. and its affiliates. - */ - -import cn from 'classnames'; -import * as React from 'react'; -import {siteConfig} from 'siteConfig'; -import {forwardRefWithAs} from 'utils/forwardRefWithAs'; -export interface HeadingProps { - className?: string; - isPageAnchor?: boolean; - children: React.ReactNode; - id?: string; - as?: any; -} - -const anchorClassName = siteConfig.headerIdConfig.className; - -const Heading = forwardRefWithAs(function Heading( - {as: Comp = 'div', className, children, id, isPageAnchor = true, ...props}, - ref -) { - return ( - <> - - {children} - {isPageAnchor && ( - - )} - - - - ); -}); - -Heading.displayName = 'Heading'; - -export const H1 = ({className, ...props}: HeadingProps) => ( - -); - -export const H2 = ({className, ...props}: HeadingProps) => ( - -); -export const H3 = ({className, ...props}: HeadingProps) => ( - -); - -export const H4 = ({className, ...props}: HeadingProps) => ( - -); diff --git a/beta/src/components/MDX/HomepageHero.tsx b/beta/src/components/MDX/HomepageHero.tsx deleted file mode 100644 index 14f2580d5..000000000 --- a/beta/src/components/MDX/HomepageHero.tsx +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Copyright (c) Facebook, Inc. and its affiliates. - */ - -import * as React from 'react'; -import {Logo} from 'components/Logo'; -import YouWillLearnCard from 'components/MDX/YouWillLearnCard'; - -function HomepageHero() { - return ( - <> -
    - -
    -

    - React Docs -

    -
    - Beta -
    -
    -
    -
    -
    - -

    - Learn how to think in React with step-by-step explanations and - interactive examples. -

    -
    -
    -
    - -

    - Look up the API signatures of React Hooks, and see their shape - using the visual code diagrams. -

    -
    -
    -
    - - ); -} - -export default HomepageHero; diff --git a/beta/src/components/MDX/InlineCode.tsx b/beta/src/components/MDX/InlineCode.tsx deleted file mode 100644 index 5a8c01938..000000000 --- a/beta/src/components/MDX/InlineCode.tsx +++ /dev/null @@ -1,31 +0,0 @@ -/* - * Copyright (c) Facebook, Inc. and its affiliates. - */ - -import * as React from 'react'; -import cn from 'classnames'; - -interface InlineCodeProps { - isLink: boolean; -} -function InlineCode({ - isLink, - ...props -}: JSX.IntrinsicElements['code'] & InlineCodeProps) { - return ( - - ); -} - -InlineCode.displayName = 'InlineCode'; - -export default InlineCode; diff --git a/beta/src/components/MDX/Intro.tsx b/beta/src/components/MDX/Intro.tsx deleted file mode 100644 index a4e81564c..000000000 --- a/beta/src/components/MDX/Intro.tsx +++ /dev/null @@ -1,21 +0,0 @@ -/* - * Copyright (c) Facebook, Inc. and its affiliates. - */ - -import React, {ReactNode} from 'react'; - -export interface IntroProps { - children?: React.ReactNode; -} - -function Intro({children}: IntroProps) { - return ( -
    - {children} -
    - ); -} - -Intro.displayName = 'Intro'; - -export default Intro; diff --git a/beta/src/components/MDX/Link.tsx b/beta/src/components/MDX/Link.tsx deleted file mode 100644 index 713d6116f..000000000 --- a/beta/src/components/MDX/Link.tsx +++ /dev/null @@ -1,59 +0,0 @@ -/* - * Copyright (c) Facebook, Inc. and its affiliates. - */ - -import * as React from 'react'; -import NextLink from 'next/link'; -import cn from 'classnames'; - -import {ExternalLink} from 'components/ExternalLink'; - -function Link({ - href, - className, - children, - ...props -}: JSX.IntrinsicElements['a']) { - const classes = - 'inline text-link dark:text-link-dark break-normal border-b border-link border-opacity-0 hover:border-opacity-100 duration-100 ease-in transition leading-normal'; - const modifiedChildren = React.Children.toArray(children).map( - (child: any, idx: number) => { - if (child.props?.mdxType && child.props?.mdxType === 'inlineCode') { - return React.cloneElement(child, { - isLink: true, - }); - } - return child; - } - ); - - if (!href) { - // eslint-disable-next-line jsx-a11y/anchor-has-content - return ; - } - return ( - <> - {href.startsWith('https://') ? ( - - {modifiedChildren} - - ) : href.startsWith('#') ? ( - // eslint-disable-next-line jsx-a11y/anchor-has-content - - {modifiedChildren} - - ) : ( - - {/* eslint-disable-next-line jsx-a11y/anchor-has-content */} - - {modifiedChildren} - - - )} - - ); -} - -Link.displayName = 'Link'; - -export default Link; diff --git a/beta/src/components/MDX/MDXComponents.tsx b/beta/src/components/MDX/MDXComponents.tsx deleted file mode 100644 index 794aac431..000000000 --- a/beta/src/components/MDX/MDXComponents.tsx +++ /dev/null @@ -1,381 +0,0 @@ -/* - * Copyright (c) Facebook, Inc. and its affiliates. - */ - -import * as React from 'react'; - -import {APIAnatomy, AnatomyStep} from './APIAnatomy'; -import CodeBlock from './CodeBlock'; -import {CodeDiagram} from './CodeDiagram'; -import ConsoleBlock from './ConsoleBlock'; -import Convention from './Convention'; -import ExpandableCallout from './ExpandableCallout'; -import ExpandableExample from './ExpandableExample'; -import {H1, H2, H3, H4} from './Heading'; -import HomepageHero from './HomepageHero'; -import InlineCode from './InlineCode'; -import Intro from './Intro'; -import Link from './Link'; -import {PackageImport} from './PackageImport'; -import Recap from './Recap'; -import Sandpack from './Sandpack'; -import SimpleCallout from './SimpleCallout'; -import TerminalBlock from './TerminalBlock'; -import YouWillLearnCard from './YouWillLearnCard'; -import {Challenges, Hint, Solution} from './Challenges'; -import {IconNavArrow} from '../Icon/IconNavArrow'; -import ButtonLink from 'components/ButtonLink'; - -const P = (p: JSX.IntrinsicElements['p']) => ( -

    -); - -const Strong = (strong: JSX.IntrinsicElements['strong']) => ( - -); - -const OL = (p: JSX.IntrinsicElements['ol']) => ( -

      -); -const LI = (p: JSX.IntrinsicElements['li']) => ( -
    1. -); -const UL = (p: JSX.IntrinsicElements['ul']) => ( -
        -); - -const Divider = () => ( -
        -); - -const Gotcha = ({children}: {children: React.ReactNode}) => ( - {children} -); -const Note = ({children}: {children: React.ReactNode}) => ( - {children} -); - -const Blockquote = ({ - children, - ...props -}: JSX.IntrinsicElements['blockquote']) => { - return ( - <> -
        - {children} -
        - - - ); -}; - -function LearnMore({ - children, - path, -}: { - title: string; - path?: string; - children: any; -}) { - return ( - <> -
        -
        -

        - 이 주제λ₯Ό 배울 μ€€λΉ„κ°€ λ˜μ—ˆλ‚˜μš”? -

        - {children} - {path ? ( - - 더 읽어보기 - - - ) : null} -
        -
        -
        - - ); -} - -function Math({children}: {children: any}) { - return ( - - {children} - - ); -} - -function MathI({children}: {children: any}) { - return ( - - {children} - - ); -} - -<<<<<<< HEAD -function YouWillLearn({children}: {children: any}) { - return {children}; -======= -function YouWillLearn({ - children, - isChapter, -}: { - children: any; - isChapter?: boolean; -}) { - let title = isChapter ? 'In this chapter' : 'You will learn'; - return {children}; ->>>>>>> 5f0549c86e7a9c0774e66687d1bc0118a681eb9d -} - -// TODO: typing. -function Recipes(props: any) { - return ; -} - -function AuthorCredit({ - author, - authorLink, -}: { - author: string; - authorLink: string; -}) { - return ( -

        - - Illustrated by{' '} - {authorLink ? ( - - {author} - - ) : ( - author - )} - -

        - ); -} - -function Illustration({ - caption, - src, - alt, - author, - authorLink, - children, -}: { - caption: string; - src: string; - alt: string; - author: string; - authorLink: string; - children: any; -}) { - return ( -
        -
        - {alt} - {caption ? ( -
        - {caption} -
        - ) : null} -
        - {author ? : null} -
        - ); -} - -function IllustrationBlock({ - title, - sequential, - author, - authorLink, - children, -}: { - title: string; - author: string; - authorLink: string; - sequential: boolean; - children: any; -}) { - const imageInfos = React.Children.toArray(children).map( - (child: any) => child.props - ); - const images = imageInfos.map((info, index) => ( -
        -
        - {info.alt} -
        - {info.caption ? ( -
        - {info.caption} -
        - ) : null} -
        - )); - return ( -
        - {title ? ( -

        - {title} -

        - ) : null} - {sequential ? ( -
          - {images.map((x: any, i: number) => ( -
        1. - {x} -
        2. - ))} -
        - ) : ( -
        {images}
        - )} - {author ? : null} - -
        - ); -} - -export const MDXComponents = { - p: P, - strong: Strong, - blockquote: Blockquote, - ol: OL, - ul: UL, - li: LI, - h1: H1, - h2: H2, - h3: H3, - h4: H4, - inlineCode: InlineCode, - hr: Divider, - a: Link, - code: CodeBlock, - // The code block renders
         so we just want a div here.
        -  pre: (p: JSX.IntrinsicElements['div']) => 
        , - // Scary: dynamic(() => import('./Scary')), - APIAnatomy, - AnatomyStep, - CodeDiagram, - ConsoleBlock, - Convention, - DeepDive: (props: { - children: React.ReactNode; - title: string; - excerpt: string; - }) => , - Gotcha, - HomepageHero, - Illustration, - IllustrationBlock, - Intro, - LearnMore, - Math, - MathI, - Note, - PackageImport, - Recap, - Recipes, - Sandpack, - TerminalBlock, - YouWillLearn, - YouWillLearnCard, - Challenges, - Hint, - Solution, -}; diff --git a/beta/src/components/MDX/PackageImport.tsx b/beta/src/components/MDX/PackageImport.tsx deleted file mode 100644 index edb2b6d0f..000000000 --- a/beta/src/components/MDX/PackageImport.tsx +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Copyright (c) Facebook, Inc. and its affiliates. - */ - -import * as React from 'react'; -import CodeBlock from './CodeBlock'; - -interface PackageImportProps { - children: React.ReactNode; -} - -export function PackageImport({children}: PackageImportProps) { - const terminal = React.Children.toArray(children).filter((child: any) => { - return child.props?.mdxType !== 'pre'; - }); - const code = React.Children.toArray(children).map((child: any, i: number) => { - if (child.props?.mdxType === 'pre') { - return ( - - ); - } else { - return null; - } - }); - return ( -
        -
        {terminal}
        -
        {code}
        -
        - ); -} diff --git a/beta/src/components/MDX/Recap.tsx b/beta/src/components/MDX/Recap.tsx deleted file mode 100644 index 9c5b08c8d..000000000 --- a/beta/src/components/MDX/Recap.tsx +++ /dev/null @@ -1,23 +0,0 @@ -/* - * Copyright (c) Facebook, Inc. and its affiliates. - */ - -import * as React from 'react'; -import {H2} from './Heading'; - -interface RecapProps { - children: React.ReactNode; -} - -function Recap({children}: RecapProps) { - return ( -
        -

        - μš”μ•½ -

        - {children} -
        - ); -} - -export default Recap; diff --git a/beta/src/components/MDX/Sandpack/CustomPreset.tsx b/beta/src/components/MDX/Sandpack/CustomPreset.tsx deleted file mode 100644 index be5115205..000000000 --- a/beta/src/components/MDX/Sandpack/CustomPreset.tsx +++ /dev/null @@ -1,126 +0,0 @@ -/* - * Copyright (c) Facebook, Inc. and its affiliates. - */ - -import React from 'react'; -// @ts-ignore -import {flushSync} from 'react-dom'; -import { - useSandpack, - useActiveCode, - SandpackCodeEditor, - SandpackThemeProvider, - SandpackReactDevTools, -} from '@codesandbox/sandpack-react'; -import scrollIntoView from 'scroll-into-view-if-needed'; - -import cn from 'classnames'; - -import {IconChevron} from 'components/Icon/IconChevron'; -import {NavigationBar} from './NavigationBar'; -import {Preview} from './Preview'; -import {CustomTheme} from './Themes'; - -export function CustomPreset({ - isSingleFile, - showDevTools, - onDevToolsLoad, - devToolsLoaded, -}: { - isSingleFile: boolean; - showDevTools: boolean; - devToolsLoaded: boolean; - onDevToolsLoad: () => void; -}) { - const lineCountRef = React.useRef<{[key: string]: number}>({}); - const containerRef = React.useRef(null); - const {sandpack} = useSandpack(); - const {code} = useActiveCode(); - const [isExpanded, setIsExpanded] = React.useState(false); - - const {activePath} = sandpack; - if (!lineCountRef.current[activePath]) { - lineCountRef.current[activePath] = code.split('\n').length; - } - const lineCount = lineCountRef.current[activePath]; - const isExpandable = lineCount > 16 || isExpanded; - const editorHeight = isExpandable ? lineCount * 24 + 24 : 'auto'; // shown lines * line height (24px) - const getHeight = () => { - if (!isExpandable) { - return editorHeight; - } - return isExpanded ? editorHeight : 406; - }; - - return ( - <> -
        - - -
        - - - - {isExpandable && ( - - )} -
        - - {showDevTools && ( - - )} -
        -
        - - ); -} diff --git a/beta/src/components/MDX/Sandpack/DownloadButton.tsx b/beta/src/components/MDX/Sandpack/DownloadButton.tsx deleted file mode 100644 index 1404aaaee..000000000 --- a/beta/src/components/MDX/Sandpack/DownloadButton.tsx +++ /dev/null @@ -1,86 +0,0 @@ -/* - * Copyright (c) Facebook, Inc. and its affiliates. - */ - -import * as React from 'react'; -import {useSandpack} from '@codesandbox/sandpack-react'; -import {IconArrowSmall} from '../../Icon/IconArrowSmall'; -export interface DownloadButtonProps {} - -export const DownloadButton: React.FC = () => { - const {sandpack} = useSandpack(); - const [supported, setSupported] = React.useState(false); - React.useEffect(() => { - // This detection will work in Chrome 97+ - if ( - (HTMLScriptElement as any).supports && - (HTMLScriptElement as any).supports('importmap') - ) { - setSupported(true); - } - }, []); - - if (!supported) { - return null; - } - - const downloadHTML = () => { - const css = sandpack.files['/styles.css']?.code ?? ''; - const code = sandpack.files['/App.js']?.code ?? ''; - const blob = new Blob([ - ` - - -
        - - - - - - - -`, - ]); - const url = window.URL.createObjectURL(blob); - const a = document.createElement('a'); - a.style.display = 'none'; - a.href = url; - a.download = 'sandbox.html'; - document.body.appendChild(a); - a.click(); - window.URL.revokeObjectURL(url); - }; - - return ( - - ); -}; diff --git a/beta/src/components/MDX/Sandpack/Error.tsx b/beta/src/components/MDX/Sandpack/Error.tsx deleted file mode 100644 index 257ce0369..000000000 --- a/beta/src/components/MDX/Sandpack/Error.tsx +++ /dev/null @@ -1,26 +0,0 @@ -/* - * Copyright (c) Facebook, Inc. and its affiliates. - */ - -import * as React from 'react'; - -interface ErrorType { - title?: string; - message: string; - column?: number; - line?: number; - path?: string; -} - -export function Error({error}: {error: ErrorType}) { - const {message, title} = error; - - return ( -
        -

        {title || 'Error'}

        -
        -        {message}
        -      
        -
        - ); -} diff --git a/beta/src/components/MDX/Sandpack/FilesDropdown.tsx b/beta/src/components/MDX/Sandpack/FilesDropdown.tsx deleted file mode 100644 index 68d068ad7..000000000 --- a/beta/src/components/MDX/Sandpack/FilesDropdown.tsx +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Copyright (c) Facebook, Inc. and its affiliates. - */ - -import * as React from 'react'; -import cn from 'classnames'; -import {IconChevron} from '../../Icon/IconChevron'; -import {useSandpack} from '@codesandbox/sandpack-react'; -import {Listbox} from '@headlessui/react'; - -const getFileName = (filePath: string): string => { - const lastIndexOfSlash = filePath.lastIndexOf('/'); - return filePath.slice(lastIndexOfSlash + 1); -}; - -export function FilesDropdown() { - const {sandpack} = useSandpack(); - const {openPaths, setActiveFile, activePath} = sandpack; - return ( - - - {({open}) => ( - - {getFileName(activePath)} - - - - - )} - - - {openPaths.map((filePath: string) => ( - - {getFileName(filePath)} - - ))} - - - ); -} diff --git a/beta/src/components/MDX/Sandpack/NavigationBar.tsx b/beta/src/components/MDX/Sandpack/NavigationBar.tsx deleted file mode 100644 index 729dcf3b0..000000000 --- a/beta/src/components/MDX/Sandpack/NavigationBar.tsx +++ /dev/null @@ -1,63 +0,0 @@ -/* - * Copyright (c) Facebook, Inc. and its affiliates. - */ - -import * as React from 'react'; -import { - FileTabs, - useSandpack, - useSandpackNavigation, -} from '@codesandbox/sandpack-react'; -import {OpenInCodeSandboxButton} from './OpenInCodeSandboxButton'; -import {ResetButton} from './ResetButton'; -import {DownloadButton} from './DownloadButton'; -import {FilesDropdown} from './FilesDropdown'; - -export function NavigationBar({showDownload}: {showDownload: boolean}) { - const {sandpack} = useSandpack(); - const [dropdownActive, setDropdownActive] = React.useState(false); - const {openPaths, clients} = sandpack; - const clientId = Object.keys(clients)[0]; - const {refresh} = useSandpackNavigation(clientId); - - const resizeHandler = React.useCallback(() => { - const width = window.innerWidth || document.documentElement.clientWidth; - if (!dropdownActive && width < 640) { - setDropdownActive(true); - } - if (dropdownActive && width >= 640) { - setDropdownActive(false); - } - }, [dropdownActive]); - - React.useEffect(() => { - if (openPaths.length > 1) { - resizeHandler(); - window.addEventListener('resize', resizeHandler); - return () => { - window.removeEventListener('resize', resizeHandler); - }; - } - return; - }, [openPaths.length, resizeHandler]); - - const handleReset = () => { - sandpack.resetAllFiles(); - refresh(); - }; - - return ( -
        -
        - {dropdownActive ? : } -
        -
        - {showDownload && } - - -
        -
        - ); -} diff --git a/beta/src/components/MDX/Sandpack/OpenInCodeSandboxButton.tsx b/beta/src/components/MDX/Sandpack/OpenInCodeSandboxButton.tsx deleted file mode 100644 index 2a06123a3..000000000 --- a/beta/src/components/MDX/Sandpack/OpenInCodeSandboxButton.tsx +++ /dev/null @@ -1,22 +0,0 @@ -/* - * Copyright (c) Facebook, Inc. and its affiliates. - */ - -import * as React from 'react'; -import {UnstyledOpenInCodeSandboxButton} from '@codesandbox/sandpack-react'; -import {IconNewPage} from '../../Icon/IconNewPage'; - -export const OpenInCodeSandboxButton = () => { - return ( - - - Fork - - ); -}; diff --git a/beta/src/components/MDX/Sandpack/Preview.tsx b/beta/src/components/MDX/Sandpack/Preview.tsx deleted file mode 100644 index bc7a37a6d..000000000 --- a/beta/src/components/MDX/Sandpack/Preview.tsx +++ /dev/null @@ -1,182 +0,0 @@ -/* - * Copyright (c) Facebook, Inc. and its affiliates. - */ - -/* eslint-disable react-hooks/exhaustive-deps */ -import * as React from 'react'; -import {useSandpack, LoadingOverlay} from '@codesandbox/sandpack-react'; -import cn from 'classnames'; - -import {Error} from './Error'; -import {computeViewportSize, generateRandomId} from './utils'; - -type CustomPreviewProps = { - className?: string; - customStyle: Record; - isExpanded: boolean; -}; - -function useDebounced(value: any): any { - const ref = React.useRef(null); - const [saved, setSaved] = React.useState(value); - React.useEffect(() => { - clearTimeout(ref.current); - ref.current = setTimeout(() => { - setSaved(value); - }, 300); - }, [value]); - return saved; -} - -export function Preview({ - customStyle, - isExpanded, - className, -}: CustomPreviewProps) { - const {sandpack, listen} = useSandpack(); - const [isReady, setIsReady] = React.useState(false); - const [iframeComputedHeight, setComputedAutoHeight] = React.useState< - number | null - >(null); - - let { - error: rawError, - registerBundler, - unregisterBundler, - errorScreenRegisteredRef, - openInCSBRegisteredRef, - loadingScreenRegisteredRef, - } = sandpack; - - if ( - rawError && - rawError.message === '_csbRefreshUtils.prelude is not a function' - ) { - // Work around a noisy internal error. - rawError = null; - } - // It changes too fast, causing flicker. - const error = useDebounced(rawError); - - const clientId = React.useRef(generateRandomId()); - const iframeRef = React.useRef(null); - - // SandpackPreview immediately registers the custom screens/components so the bundler does not render any of them - // TODO: why are we doing this during render? - openInCSBRegisteredRef.current = true; - errorScreenRegisteredRef.current = true; - loadingScreenRegisteredRef.current = true; - - React.useEffect(() => { - const iframeElement = iframeRef.current!; - registerBundler(iframeElement, clientId.current); - - const unsub = listen((message: any) => { - if (message.type === 'resize') { - setComputedAutoHeight(message.height); - } else if (message.type === 'start') { - if (message.firstLoad) { - setIsReady(false); - } - } else if (message.type === 'test') { - // Does it make sense that we're listening to "test" event? - // Not really. Does it cause less flicker than "done"? Yes. - setIsReady(true); - } - }, clientId.current); - - return () => { - unsub(); - unregisterBundler(clientId.current); - }; - }, []); - - const viewportStyle = computeViewportSize('auto', 'portrait'); - const overrideStyle = error - ? { - // Don't collapse errors - maxHeight: undefined, - } - : null; - const hideContent = !isReady || error; - - // WARNING: - // The layout and styling here is convoluted and really easy to break. - // If you make changes to it, you need to test different cases: - // - Content -> (compile | runtime) error -> content editing flow should work. - // - Errors should expand parent height rather than scroll. - // - Long sandboxes should scroll unless "show more" is toggled. - // - Expanded sandboxes ("show more") have sticky previews and errors. - // - Sandboxes have autoheight based on content. - // - That autoheight should be measured correctly! (Check some long ones.) - // - You shouldn't see nested scrolls (that means autoheight is borked). - // - Ideally you shouldn't see a blank preview tile while recompiling. - // - Container shouldn't be horizontally scrollable (even while loading). - // - It should work on mobile. - // The best way to test it is to actually go through some challenges. - - return ( -
        -
        -
        - - -## Snake in React {/*snake-in-react*/} - -[Tom Occhino](http://tomocchino.com/) implemented Snake in 150 lines with React. - -> [Check the source on GitHub](https://github.com/tomocchino/react-snake/blob/master/src/snake.js) -> ->
        diff --git a/beta/src/pages/blog/2013/07/11/react-v0-4-prop-validation-and-default-values.md b/beta/src/pages/blog/2013/07/11/react-v0-4-prop-validation-and-default-values.md deleted file mode 100644 index 59a41733c..000000000 --- a/beta/src/pages/blog/2013/07/11/react-v0-4-prop-validation-and-default-values.md +++ /dev/null @@ -1,60 +0,0 @@ ---- -title: 'New in React v0.4: Prop Validation and Default Values' -author: [zpao] ---- - -Many of the questions we got following the public launch of React revolved around `props`, specifically that people wanted to do validation and to make sure their components had sensible defaults. - -## Validation {/*validation*/} - -Oftentimes you want to validate your `props` before you use them. Perhaps you want to ensure they are a specific type. Or maybe you want to restrict your prop to specific values. Or maybe you want to make a specific prop required. This was always possible β€” you could have written validations in your `render` or `componentWillReceiveProps` functions, but that gets clunky fast. - -React v0.4 will provide a nice easy way for you to use built-in validators, or to even write your own. - -```js -React.createClass({ - propTypes: { - // An optional string prop named "description". - description: React.PropTypes.string, - - // A required enum prop named "category". - category: React.PropTypes.oneOf(['News','Photos']).isRequired, - - // A prop named "dialog" that requires an instance of Dialog. - dialog: React.PropTypes.instanceOf(Dialog).isRequired - }, - ... -}); -``` - -## Default Values {/*default-values*/} - -One common pattern we've seen with our React code is to do something like this: - -```js -React.createClass({ - render: function () { - var value = this.props.value || 'default value'; - return
        {value}
        ; - }, -}); -``` - -Do this for a few `props` across a few components and now you have a lot of redundant code. Starting with React v0.4, you can provide default values in a declarative way: - -```js -React.createClass({ - getDefaultProps: function() { - return { - value: 'default value' - }; - } - ... -}); -``` - -We will use the cached result of this function before each `render`. We also perform all validations before each `render` to ensure that you have all of the data you need in the right form before you try to use it. - ---- - -Both of these features are entirely optional. We've found them to be increasingly valuable at Facebook as our applications grow and evolve, and we hope others find them useful as well. diff --git a/beta/src/pages/blog/2013/07/17/react-v0-4-0.md b/beta/src/pages/blog/2013/07/17/react-v0-4-0.md deleted file mode 100644 index 65a730234..000000000 --- a/beta/src/pages/blog/2013/07/17/react-v0-4-0.md +++ /dev/null @@ -1,37 +0,0 @@ ---- -title: 'React v0.4.0' -author: [zpao] ---- - -Over the past 2 months we've been taking feedback and working hard to make React even better. We fixed some bugs, made some under-the-hood improvements, and added several features that we think will improve the experience developing with React. Today we're proud to announce the availability of React v0.4! - -This release could not have happened without the support of our growing community. Since launch day, the community has contributed blog posts, questions to the [Google Group](https://groups.google.com/group/reactjs), and issues and pull requests on GitHub. We've had contributions ranging from documentation improvements to major changes to React's rendering. We've seen people integrate React into the tools they're using and the products they're building, and we're all very excited to see what our budding community builds next! - -React v0.4 has some big changes. We've also restructured the documentation to better communicate how to use React. We've summarized the changes below and linked to documentation where we think it will be especially useful. - -When you're ready, [go download it](/docs/installation.html)! - -### React {/*react*/} - -- Switch from using `id` attribute to `data-reactid` to track DOM nodes. This allows you to integrate with other JS and CSS libraries more easily. -- Support for more DOM elements and attributes (e.g., ``) -- Improved server-side rendering APIs. `React.renderComponentToString(, callback)` allows you to use React on the server and generate markup which can be sent down to the browser. -- `prop` improvements: validation and default values. [Read our blog post for details...](/blog/2013/07/11/react-v0-4-prop-validation-and-default-values.html) -- Support for the `key` prop, which allows for finer control over reconciliation. [Read the docs for details...](/docs/multiple-components.html) -- Removed `React.autoBind`. [Read our blog post for details...](/blog/2013/07/02/react-v0-4-autobind-by-default.html) -- Improvements to forms. We've written wrappers around ``, ` -
        - - - - -

        That's right!

        - - -``` - - - -Manipulating the UI imperatively works well enough for isolated examples, but it gets exponentially more difficult to manage in more complex systems. Imagine updating a page full of different forms like this one. Adding a new UI element or a new interaction would require carefully checking all existing code to make sure you haven't introduced a bug (for example, forgetting to show or hide something). - -React was built to solve this problem. - -In React, you don't directly manipulate the UI--meaning you don't enable, disable, show, or hide components directly. Instead, you **declare what you want to show**, and React figures out how to update the UI. Think of getting into a taxi and telling the driver where you want to go instead of telling them exactly where to turn. It's the driver's job to get you there, and they might even know some shortcuts you haven't considered! - - - -## Thinking about UI declaratively {/*thinking-about-ui-declaratively*/} - -You've seen how to implement a form imperatively above. To better understand how to think in React, you'll walk through reimplementing this UI in React below: - -1. **Identify** your component's different visual states -2. **Determine** what triggers those state changes -3. **Represent** the state in memory using `useState` -4. **Remove** any non-essential state variables -5. **Connect** the event handlers to set the state - -### Step 1: Identify your component's different visual states {/*step-1-identify-your-components-different-visual-states*/} - -In computer science, you may hear about a ["state machine"](https://en.wikipedia.org/wiki/Finite-state_machine) being in one of several β€œstates”. If you work with a designer, you may have seen mockups for different "visual states". React stands at the intersection of design and computer science, so both of these ideas are sources of inspiration. - -First, you need to visualize all the different "states" of the UI the user might see: - -* **Empty**: Form has a disabled "Submit" button. -* **Typing**: Form has an enabled "Submit" button. -* **Submitting**: Form is completely disabled. Spinner is shown. -* **Success**: "Thank you" message is shown instead of a form. -* **Error**: Same as Typing state, but with an extra error message. - -Just like a designer, you'll want to "mock up" or create "mocks" for the different states before you add logic. For example, here is a mock for just the visual part of the form. This mock is controlled by a prop called `status` with a default value of `'empty'`: - - - -```js -export default function Form({ - status = 'empty' -}) { - if (status === 'success') { - return

        That's right!

        - } - return ( - <> -

        City quiz

        -

        - In which city is there a billboard that turns air into drinkable water? -

        -
        - -``` - -Reactμ—μ„œ ` +
        + + + +
        +

        That's right!

        + + +``` + +
        + +μœ„μ˜ μ˜ˆμ‹œμ—μ„œλŠ” λ¬Έμ œκ°€ μ—†κ² μ§€λ§Œ μœ„μ™€ 같이 UIλ₯Ό μ‘°μž‘ν•˜λ©΄ 더 λ³΅μž‘ν•œ μ‹œμŠ€ν…œμ—μ„œλŠ” λ‚œμ΄λ„κ°€ κΈ°ν•˜κΈ‰μˆ˜μ μœΌλ‘œ μ˜¬λΌκ°‘λ‹ˆλ‹€. μ—¬λŸ¬ λ‹€λ₯Έ 폼으둜 가득 μ°¬ νŽ˜μ΄μ§€λ₯Ό μ—…λ°μ΄νŠΈν•΄μ•Ό ν•œλ‹€κ³  μƒκ°ν•΄λ³΄μ„Έμš”. μƒˆλ‘œμš΄ UI μš”μ†Œλ‚˜ μƒˆλ‘œμš΄ μƒν˜Έμž‘μš©μ„ μΆ”κ°€ν•˜λ €λ©΄ λ²„κ·Έμ˜ λ°œμƒμ„ 막기 μœ„ν•΄ 기쑴의 λͺ¨λ“  μ½”λ“œλ₯Ό 주의 깊게 μ‚΄νŽ΄λ΄μ•Όλ§Œ ν•  κ²λ‹ˆλ‹€. (예λ₯Ό λ“€λ©΄ μ–΄λ–€ 것을 λ³΄μ—¬μ£Όκ±°λ‚˜ μˆ¨κΈ°κ±°λ‚˜ ν•˜λŠ” 것을 μžŠμ„μ§€λ„ λͺ¨λ¦…λ‹ˆλ‹€). + +ReactλŠ” μ΄λŸ¬ν•œ λ¬Έμ œμ μ„ ν•΄κ²°ν•˜κΈ° μœ„ν•΄ λ§Œλ“€μ–΄μ‘ŒμŠ΅λ‹ˆλ‹€. + +Reactμ—μ„œλŠ” 직접 UIλ₯Ό μ‘°μž‘ν•  ν•„μš”κ°€ μ—†μŠ΅λ‹ˆλ‹€. μ»΄ν¬λ„ŒνŠΈλ₯Ό 직접 ν™œμ„±ν™”ν•˜κ±°λ‚˜ λΉ„ν™œμ„±ν™”ν•˜κ±°λ‚˜ λ³΄μ—¬μ£Όκ±°λ‚˜ 숨길 ν•„μš”κ°€ μ—†μŠ΅λ‹ˆλ‹€. λŒ€μ‹ μ— **무엇을 보여주고 싢은지 μ„ μ–Έ**ν•˜κΈ°λ§Œ ν•˜λ©΄ λ©λ‹ˆλ‹€. 그러면 ReactλŠ” μ–΄λ–»κ²Œ UIλ₯Ό μ—…λ°μ΄νŠΈ ν•΄μ•Ό ν• μ§€ 이해할 κ²ƒμž…λ‹ˆλ‹€. νƒμ‹œλ₯Ό 탄닀고 생각해 λ΄…μ‹œλ‹€. μš΄μ „κΈ°μ‚¬μ—κ²Œ μ–΄λ””μ„œ κΊΎμ–΄μ•Ό ν• μ§€ μ•Œλ €μ£ΌλŠ”κ²Œ μ•„λ‹ˆλΌ κ°€κ³  싢은 곳을 λ§ν•œλ‹€κ³  생각해 λ³΄μ„Έμš”. 당신을 κ±°κΈ°κΉŒμ§€ λ°λ €λ‹€μ£ΌλŠ” 것은 μš΄μ „κΈ°μ‚¬μ˜ 일이고 μš΄μ „κΈ°μ‚¬λŠ” μ–΄μ©Œλ©΄ 당신이 λͺ°λžλ˜ 지름길을 μ•Œκ³  μžˆμ„μ§€λ„ λͺ¨λ¦…λ‹ˆλ‹€! + + + +## UIλ₯Ό 선언적인 λ°©μ‹μœΌλ‘œ μƒκ°ν•˜κΈ° {/*thinking-about-ui-declaratively*/} + +μ§€κΈˆκΉŒμ§€ 폼을 선언적인 λ°©μ‹μœΌλ‘œ κ΅¬ν˜„ν•˜λŠ” 방법을 μ‚΄νŽ΄λ³΄μ•˜μŠ΅λ‹ˆλ‹€. React처럼 μƒκ°ν•˜λŠ” 방법을 더 잘 μ΄ν•΄ν•˜κΈ° μœ„ν•΄ UIλ₯Ό Reactμ—μ„œ λ‹€μ‹œ κ΅¬ν˜„ν•˜λŠ” 과정을 μ•„λž˜μ—μ„œ μ‚΄νŽ΄λ΄…μ‹œλ‹€. + +1. μ»΄ν¬λ„ŒνŠΈμ˜ λ‹€μ–‘ν•œ μ‹œκ°μ  stateλ₯Ό **ν™•μΈν•˜μ„Έμš”.** +2. 무엇이 state λ³€ν™”λ₯Ό νŠΈλ¦¬κ±°ν•˜λŠ”μ§€ **μ•Œμ•„λ‚΄μ„Έμš”.** +3. `useState`λ₯Ό μ‚¬μš©ν•΄μ„œ λ©”λͺ¨λ¦¬μ˜ stateλ₯Ό **ν‘œν˜„ν•˜μ„Έμš”.** +4. λΆˆν•„μš”ν•œ state λ³€μˆ˜λ₯Ό **μ œκ±°ν•˜μ„Έμš”.** +5. state 섀정을 μœ„ν•΄ 이벀트 ν•Έλ“€λŸ¬λ₯Ό **μ—°κ²°ν•˜μ„Έμš”.** + +## 첫 번째: μ»΄ν¬λ„ŒνŠΈμ˜ λ‹€μ–‘ν•œ μ‹œκ°μ  state ν™•μΈν•˜κΈ° {/*step-1-identify-your-components-different-visual-states*/} + +μ—¬λŸ¬κ°€μ§€ "state"λ₯Ό κ°€μ§€κ³  μžˆλŠ” ["μƒνƒœ 기계"](https://ko.wikipedia.org/wiki/μœ ν•œ_μƒνƒœ_기계)λΌλŠ” 것을 컴퓨터 κ³Όν•™μ—μ„œ λ“€μ–΄λ³Έ 적이 μžˆμ„ κ²ƒμž…λ‹ˆλ‹€. 그리고 λ””μžμ΄λ„ˆμ™€ μΌν•œλ‹€λ©΄ λ‹€μ–‘ν•œ "μ‹œκ°μ  state"에 κ΄€ν•œ λͺ¨ν˜•을 λ³Έ 적이 μžˆμ„ κ²ƒμž…λ‹ˆλ‹€. ReactλŠ” λ””μžμΈκ³Ό 컴퓨터 κ³Όν•™μ˜ 사이에 있기 λ•Œλ¬Έμ— 두 아이디어 λͺ¨λ‘μ—μ„œ μ˜κ°μ„ λ°›μ•˜μŠ΅λ‹ˆλ‹€. + +λ¨Όμ € μ‚¬μš©μžκ°€ λ³Ό 수 μžˆλŠ” UI의 λͺ¨λ“  "state"λ₯Ό μ‹œκ°ν™”ν•΄μ•Ό ν•©λ‹ˆλ‹€. + +* **Empty**: 폼은 λΉ„ν™œμ„±ν™”λœ "제좜" λ²„νŠΌμ„ κ°€μ§€κ³  μžˆλ‹€. +* **Typing**: 폼은 ν™œμ„±ν™”λœ "제좜" λ²„νŠΌμ„ κ°€μ§€κ³  μžˆλ‹€. +* **Submitting**: 폼은 μ™„μ „νžˆ λΉ„ν™œμ„±ν™”λ˜κ³  μŠ€ν”Όλ„ˆκ°€ 보인닀. +* **Success**: 폼 λŒ€μ‹ μ— "κ°μ‚¬ν•©λ‹ˆλ‹€" λ©”μ‹œμ§€κ°€ 보인닀. +* **Error**: "Typing" state와 λ™μΌν•˜μ§€λ§Œ 였λ₯˜ λ©”μ‹œμ§€κ°€ 보인닀. + +λ””μžμ΄λ„ˆμ²˜λŸΌ λ‘œμ§μ„ μΆ”κ°€ν•˜κΈ° 전에 μ—¬λŸ¬ stateλ₯Ό "λͺ©μ—…" ν•˜κ±°λ‚˜ "λͺ¨ν˜•"을 λ§Œλ“€κ³  싢을 κ²ƒμž…λ‹ˆλ‹€. 여기에 폼의 μƒκΉ€μƒˆμ™€ κ΄€λ ¨λœ λͺ¨ν˜•이 μžˆλ‹€κ³  μƒκ°ν•΄λ΄…μ‹œλ‹€. 이 λͺ¨ν˜•은 기본값이 `'empty'`인 `status` prop에 μ˜ν•΄ μ»¨νŠΈλ‘€λ©λ‹ˆλ‹€. + + + +```js +export default function Form({ + status = 'empty' +}) { + if (status === 'success') { + return

        That's right!

        + } + return ( + <> +

        City quiz

        +

        + In which city is there a billboard that turns air into drinkable water? +

        +
        + `와 같이 μžμ‹μ„ μ „λ‹¬ν•˜λŠ” 것은 ν—ˆμš©λ˜μ§€ μ•ŠμŠ΅λ‹ˆλ‹€. [초기 μ½˜ν…μΈ λ‘œ `defaultValue`λ₯Ό μ‚¬μš©ν•˜μ„Έμš”.](#providing-an-initial-value-for-a-text-area) +- ν…μŠ€νŠΈ μ˜μ—­μ€ λ¬Έμžμ—΄ `value` Prop을 받을 경우 [μ œμ–΄λ˜λŠ” κ²ƒμœΌλ‘œ μ·¨κΈ‰](#controlling-a-text-area-with-a-state-variable)λ©λ‹ˆλ‹€. +- ν…μŠ€νŠΈ μ˜μ—­μ€ μ œμ–΄λ˜λ©΄μ„œ λ™μ‹œμ— λΉ„μ œμ–΄λ  수 μ—†μŠ΅λ‹ˆλ‹€. +- ν…μŠ€νŠΈ μ˜μ—­μ€ 생λͺ…μ£ΌκΈ° λ™μ•ˆ μ œμ–΄ λ˜λŠ” λΉ„μ œμ–΄ μƒνƒœλ₯Ό 였갈 수 μ—†μŠ΅λ‹ˆλ‹€. +- μ œμ–΄λ˜λŠ” ν…μŠ€νŠΈ μ˜μ—­μ—” λͺ¨λ‘ λ°±μ—… 값을 λ™κΈ°μ μœΌλ‘œ μ—…λ°μ΄νŠΈν•˜λŠ” `onChange` 이벀트 ν•Έλ“€λŸ¬κ°€ ν•„μš”ν•©λ‹ˆλ‹€. + +--- + +## μ‚¬μš©λ²• {/*usage*/} + +### ν…μŠ€νŠΈ μ˜μ—­ ν‘œμ‹œν•˜κΈ° {/*displaying-a-text-area*/} + +ν…μŠ€νŠΈ μ˜μ—­μ„ ν‘œμ‹œν•˜λ €λ©΄ ``와 같은 초기 ν…μŠ€νŠΈ 전달은 μ§€μ›λ˜μ§€ μ•ŠμŠ΅λ‹ˆλ‹€. + + + +--- + +### 폼 제좜 μ‹œ ν…μŠ€νŠΈ μ˜μ—­ κ°’ 읽기 {/*reading-the-text-area-value-when-submitting-a-form*/} + +ν…μŠ€νŠΈ μ˜μ—­κ³Ό [`