diff --git a/src/components/MDX/Sandpack/DownloadButton.tsx b/src/components/MDX/Sandpack/DownloadButton.tsx index d6b1c3299..94cf13ddc 100644 --- a/src/components/MDX/Sandpack/DownloadButton.tsx +++ b/src/components/MDX/Sandpack/DownloadButton.tsx @@ -5,6 +5,7 @@ import {useSyncExternalStore} from 'react'; import {useSandpack} from '@codesandbox/sandpack-react/unstyled'; import {IconDownload} from '../../Icon/IconDownload'; +import {AppJSPath, StylesCSSPath, SUPPORTED_FILES} from './createFileMap'; export interface DownloadButtonProps {} let supportsImportMap = false; @@ -32,8 +33,6 @@ function useSupportsImportMap() { return useSyncExternalStore(subscribe, getCurrentValue, getServerSnapshot); } -const SUPPORTED_FILES = ['/App.js', '/styles.css']; - export function DownloadButton({ providedFiles, }: { @@ -49,8 +48,8 @@ export function DownloadButton({ } const downloadHTML = () => { - const css = sandpack.files['/styles.css']?.code ?? ''; - const code = sandpack.files['/App.js']?.code ?? ''; + const css = sandpack.files[StylesCSSPath]?.code ?? ''; + const code = sandpack.files[AppJSPath]?.code ?? ''; const blob = new Blob([ ` diff --git a/src/components/MDX/Sandpack/SandpackRoot.tsx b/src/components/MDX/Sandpack/SandpackRoot.tsx index df0c757f2..d47fd903c 100644 --- a/src/components/MDX/Sandpack/SandpackRoot.tsx +++ b/src/components/MDX/Sandpack/SandpackRoot.tsx @@ -9,6 +9,7 @@ import {SandpackLogLevel} from '@codesandbox/sandpack-client'; import {CustomPreset} from './CustomPreset'; import {createFileMap} from './createFileMap'; import {CustomTheme} from './Themes'; +import {template} from './template'; type SandpackProps = { children: React.ReactNode; @@ -70,17 +71,19 @@ function SandpackRoot(props: SandpackProps) { const codeSnippets = Children.toArray(children) as React.ReactElement[]; const files = createFileMap(codeSnippets); - files['/styles.css'] = { - code: [sandboxStyle, files['/styles.css']?.code ?? ''].join('\n\n'), - hidden: !files['/styles.css']?.visible, + files['/src/styles.css'] = { + code: [sandboxStyle, files['/src/styles.css']?.code ?? ''].join('\n\n'), + hidden: !files['/src/styles.css']?.visible, }; return (
{ return codeSnippets.reduce( (result: Record, codeSnippet: React.ReactElement) => { @@ -26,15 +30,16 @@ export const createFileMap = (codeSnippets: any) => { } } else { if (props.className === 'language-js') { - filePath = '/App.js'; + filePath = AppJSPath; } else if (props.className === 'language-css') { - filePath = '/styles.css'; + filePath = StylesCSSPath; } else { throw new Error( `Code block is missing a filename: ${props.children}` ); } } + if (result[filePath]) { throw new Error( `File ${filePath} was defined multiple times. Each file snippet should have a unique path name` diff --git a/src/components/MDX/Sandpack/index.tsx b/src/components/MDX/Sandpack/index.tsx index 6873547a1..6755ba8de 100644 --- a/src/components/MDX/Sandpack/index.tsx +++ b/src/components/MDX/Sandpack/index.tsx @@ -3,7 +3,7 @@ */ import {lazy, memo, Children, Suspense} from 'react'; -import {createFileMap} from './createFileMap'; +import {AppJSPath, createFileMap} from './createFileMap'; const SandpackRoot = lazy(() => import('./SandpackRoot')); @@ -57,7 +57,7 @@ export default memo(function SandpackWrapper(props: any): any { ); let activeCode; if (!activeCodeSnippet.length) { - activeCode = codeSnippet['/App.js'].code; + activeCode = codeSnippet[AppJSPath].code; } else { activeCode = codeSnippet[activeCodeSnippet[0]].code; } diff --git a/src/components/MDX/Sandpack/template.ts b/src/components/MDX/Sandpack/template.ts new file mode 100644 index 000000000..9ead18a14 --- /dev/null +++ b/src/components/MDX/Sandpack/template.ts @@ -0,0 +1,54 @@ +export const template = { + '/src/index.js': { + hidden: true, + code: `import React, { StrictMode } from "react"; +import { createRoot } from "react-dom/client"; +import "./styles.css"; + +import App from "./App"; + +const root = createRoot(document.getElementById("root")); +root.render( + + + +);`, + }, + '/package.json': { + hidden: true, + code: JSON.stringify( + { + name: 'react.dev', + version: '0.0.0', + main: '/src/index.js', + scripts: { + start: 'react-scripts start', + build: 'react-scripts build', + test: 'react-scripts test --env=jsdom', + eject: 'react-scripts eject', + }, + dependencies: { + react: '^18.0.0', + 'react-dom': '^18.0.0', + 'react-scripts': '^5.0.0', + }, + }, + null, + 2 + ), + }, + '/public/index.html': { + hidden: true, + code: ` + + + + + Document + + +
+ +`, + }, +}; diff --git a/src/content/blog/2023/03/16/introducing-react-dev.md b/src/content/blog/2023/03/16/introducing-react-dev.md index d27673d90..4ce209d71 100644 --- a/src/content/blog/2023/03/16/introducing-react-dev.md +++ b/src/content/blog/2023/03/16/introducing-react-dev.md @@ -57,7 +57,7 @@ If you like to learn by doing, we recommend checking out the [Tic-Tac-Toe Tutori -```js App.js +```js src/App.js import { useState } from 'react'; function Square({ value, onSquareClick }) { @@ -175,7 +175,7 @@ function calculateWinner(squares) { } ``` -```css styles.css +```css src/styles.css * { box-sizing: border-box; } @@ -428,7 +428,7 @@ export default function PackingList() { Note that you must write `importance > 0 && ...` rather than `importance && ...` so that if the `importance` is `0`, `0` isn't rendered as the result! -In this solution, two separate conditions are used to insert a space between then name and the importance label. Alternatively, you could use a fragment with a leading space: `importance > 0 && <> ...` or add a space immediately inside the ``: `importance > 0 && ...`. +In this solution, two separate conditions are used to insert a space between then name and the importance label. Alternatively, you could use a Fragment with a leading space: `importance > 0 && <> ...` or add a space immediately inside the ``: `importance > 0 && ...`. @@ -643,4 +643,3 @@ On the development front, thanks to [Jared Palmer](https://twitter.com/jaredpalm Huge thanks to the folks who volunteered their time to participate in the alpha and beta testing program. Your enthusiasm and invaluable feedback helped us shape these docs. A special shout out to our beta tester, [Debbie O'Brien](https://twitter.com/debs_obrien), who gave a talk about her experience using the React docs at React Conf 2021. Finally, thanks to the React community for being the inspiration behind this effort. You are the reason we do this, and we hope that the new docs will help you use React to build any user interface that you want. - diff --git a/src/content/community/conferences.md b/src/content/community/conferences.md index 1c164a098..9f020966e 100644 --- a/src/content/community/conferences.md +++ b/src/content/community/conferences.md @@ -10,72 +10,77 @@ Do you know of a local React.js conference? Add it here! (Please keep the list c ## Upcoming Conferences {/*upcoming-conferences*/} -### RedwoodJS Conference 2023 {/*redwoodjs-conference-2023*/} -September 26 - 29, 2023. Grants Pass, Oregon + remote (hybrid event) - -[Website](https://www.redwoodjsconf.com/) - [Twitter](https://twitter.com/redwoodjs) +### App.js Conf 2024 {/*appjs-conf-2024*/} +May 22 - 24, 2024. In-person in Kraków, Poland + remote -### React Alicante 2023 {/*react-alicante-2023*/} -September 28 - 30, 2023. Alicante, Spain +[Website](https://appjs.co) - [Twitter](https://twitter.com/appjsconf) -[Website](https://reactalicante.es/) - [Twitter](https://twitter.com/reactalicante) +### Render(ATL) 2024 🍑 {/*renderatl-2024-*/} +June 12 - June 14, 2024. Atlanta, GA, USA -### React Live 2023 {/*react-live-2023*/} -September 29, 2023. Amsterdam, Netherlands +[Website](https://renderatl.com) - [Discord](https://www.renderatl.com/discord) - [Twitter](https://twitter.com/renderATL) - [Instagram](https://www.instagram.com/renderatl/) - [Facebook](https://www.facebook.com/renderatl/) - [LinkedIn](https://www.linkedin.com/company/renderatl) - [Podcast](https://www.renderatl.com/culture-and-code#/) -[Website](https://reactlive.nl/) +### React India 2024 {/*react-india-2024*/} +October 17 - 19, 2024. In-person in Goa, India (hybrid event) + Oct 15 2024 - remote day -### React Native EU 2023 {/*react-native-eu-2023*/} -September 7 & 8, 2023. Wrocław, Poland +[Website](https://www.reactindia.io) - [Twitter](https://twitter.com/react_india) - [Facebook](https://www.facebook.com/ReactJSIndia) - [Youtube](https://www.youtube.com/channel/UCaFbHCBkPvVv1bWs_jwYt3w) -[Website](https://react-native.eu) - [Twitter](https://twitter.com/react_native_eu) - [Facebook](https://www.facebook.com/reactnativeeu) +## Past Conferences {/*past-conferences*/} -### RenderCon Kenya 2023 {/*rendercon-kenya-2023*/} -September 29 - 30, 2023. Nairobi, Kenya +### React Day Berlin 2023 {/*react-day-berlin-2023*/} +December 8 & 12, 2023. In-person in Berlin, Germany + remote first interactivity (hybrid event) -[Website](https://rendercon.org/) - [Twitter](https://twitter.com/renderconke) - [LinkedIn](https://www.linkedin.com/company/renderconke/) - [YouTube](https://www.youtube.com/channel/UC0bCcG8gHUL4njDOpQGcMIA) +[Website](https://reactday.berlin) - [Twitter](https://twitter.com/reactdayberlin) - [Facebook](https://www.facebook.com/reactdayberlin/) - [Videos](https://portal.gitnation.org/events/react-day-berlin-2023) -### React India 2023 {/*react-india-2023*/} -October 5 - 7, 2023. In-person in Goa, India (hybrid event) + Oct 3 2023 - remote day +### React Summit US 2023 {/*react-summit-us-2023*/} +November 13 & 15, 2023. In-person in New York, US + remote first interactivity (hybrid event) -[Website](https://www.reactindia.io) - [Twitter](https://twitter.com/react_india) - [Facebook](https://www.facebook.com/ReactJSIndia) - [Youtube](https://www.youtube.com/channel/UCaFbHCBkPvVv1bWs_jwYt3w) +[Website](https://reactsummit.us) - [Twitter](https://twitter.com/reactsummit) - [Facebook](https://www.facebook.com/reactamsterdam) - [Videos](https://portal.gitnation.org/events/react-summit-us-2023) -### React Brussels 2023 {/*react-brussels-2023*/} -October 13th 2023. In-person in Brussels, Belgium + Remote (hybrid) +### reactjsday 2023 {/*reactjsday-2023*/} +October 27th 2023. In-person in Verona, Italy and online (hybrid event) -[Website](https://www.react.brussels/) - [Twitter](https://twitter.com/BrusselsReact) +[Website](https://2023.reactjsday.it/) - [Twitter](https://twitter.com/reactjsday) - [Facebook](https://www.facebook.com/GrUSP/) - [YouTube](https://www.youtube.com/c/grusp) ### React Advanced 2023 {/*react-advanced-2023*/} October 20 & 23, 2023. In-person in London, UK + remote first interactivity (hybrid event) [Website](https://www.reactadvanced.com/) - [Twitter](https://twitter.com/ReactAdvanced) - [Facebook](https://www.facebook.com/ReactAdvanced) - [Videos](https://portal.gitnation.org/events/react-advanced-conference-2023) -### reactjsday 2023 {/*reactjsday-2023*/} -October 27th 2023. In-person in Verona, Italy and online (hybrid event) +### React Brussels 2023 {/*react-brussels-2023*/} +October 13th 2023. In-person in Brussels, Belgium + Remote (hybrid) -[Website](https://2023.reactjsday.it/) - [Twitter](https://twitter.com/reactjsday) - [Facebook](https://www.facebook.com/GrUSP/) - [YouTube](https://www.youtube.com/c/grusp) +[Website](https://www.react.brussels/) - [Twitter](https://twitter.com/BrusselsReact) -### React Summit US 2023 {/*react-summit-us-2023*/} -November 13 & 15, 2023. In-person in New York, US + remote first interactivity (hybrid event) +### React India 2023 {/*react-india-2023*/} +October 5 - 7, 2023. In-person in Goa, India (hybrid event) + Oct 3 2023 - remote day -[Website](https://reactsummit.us) - [Twitter](https://twitter.com/reactsummit) - [Facebook](https://www.facebook.com/reactamsterdam) - [Videos](https://portal.gitnation.org/events/react-summit-us-2023) +[Website](https://www.reactindia.io) - [Twitter](https://x.com/react_india) - [Facebook](https://www.facebook.com/ReactJSIndia) - [Youtube](https://www.youtube.com/channel/UCaFbHCBkPvVv1bWs_jwYt3w) -### React Day Berlin 2023 {/*react-day-berlin-2023*/} -December 8 & 12, 2023. In-person in Berlin, Germany + remote first interactivity (hybrid event) +### RenderCon Kenya 2023 {/*rendercon-kenya-2023*/} +September 29 - 30, 2023. Nairobi, Kenya -[Website](https://reactday.berlin) - [Twitter](https://twitter.com/reactdayberlin) - [Facebook](https://www.facebook.com/reactdayberlin/) - [Videos](https://portal.gitnation.org/events/react-day-berlin-2023) +[Website](https://rendercon.org/) - [Twitter](https://twitter.com/renderconke) - [LinkedIn](https://www.linkedin.com/company/renderconke/) - [YouTube](https://www.youtube.com/channel/UC0bCcG8gHUL4njDOpQGcMIA) -### App.js Conf 2024 {/*appjs-conf-2024*/} -May 22 - 24, 2024. In-person in Kraków, Poland + remote +### React Live 2023 {/*react-live-2023*/} +September 29, 2023. Amsterdam, Netherlands -[Website](https://appjs.co) - [Twitter](https://twitter.com/appjsconf) +[Website](https://reactlive.nl/) -### Render(ATL) 2024 🍑 {/*renderatl-2024-*/} -June 12 - June 14, 2024. Atlanta, GA, USA +### React Alicante 2023 {/*react-alicante-2023*/} +September 28 - 30, 2023. Alicante, Spain -[Website](https://renderatl.com) - [Discord](https://www.renderatl.com/discord) - [Twitter](https://twitter.com/renderATL) - [Instagram](https://www.instagram.com/renderatl/) - [Facebook](https://www.facebook.com/renderatl/) - [LinkedIn](https://www.linkedin.com/company/renderatl) - [Podcast](https://www.renderatl.com/culture-and-code#/) +[Website](https://reactalicante.es/) - [Twitter](https://twitter.com/reactalicante) -## Past Conferences {/*past-conferences*/} +### RedwoodJS Conference 2023 {/*redwoodjs-conference-2023*/} +September 26 - 29, 2023. Grants Pass, Oregon + remote (hybrid event) + +[Website](https://www.redwoodjsconf.com/) - [Twitter](https://twitter.com/redwoodjs) + +### React Native EU 2023 {/*react-native-eu-2023*/} +September 7 & 8, 2023. Wrocław, Poland + +[Website](https://react-native.eu) - [Twitter](https://twitter.com/react_native_eu) - [Facebook](https://www.facebook.com/reactnativeeu) ### React Rally 2023 🐙 {/*react-rally-2023*/} August 17 & 18, 2023. Salt Lake City, UT, USA diff --git a/src/content/community/meetups.md b/src/content/community/meetups.md index 644bbcee3..000eeb43c 100644 --- a/src/content/community/meetups.md +++ b/src/content/community/meetups.md @@ -101,6 +101,7 @@ Do you have a local React.js meetup? Add it here! (Please keep the list alphabet * [Bangalore (React Native)](https://www.meetup.com/React-Native-Bangalore-Meetup) * [Chennai](https://www.meetup.com/React-Chennai/) * [Delhi NCR](https://www.meetup.com/React-Delhi-NCR/) +* [Mumbai](https://reactmumbai.dev) * [Pune](https://www.meetup.com/ReactJS-and-Friends/) ## Indonesia {/*indonesia*/} diff --git a/src/content/community/versioning-policy.md b/src/content/community/versioning-policy.md index 68d5b8eb1..eb38f8c29 100644 --- a/src/content/community/versioning-policy.md +++ b/src/content/community/versioning-policy.md @@ -46,7 +46,7 @@ In general, we *don't* bump the major version number for changes to: * **Development warnings.** Since these don't affect production behavior, we may add new warnings or modify existing warnings in between major versions. In fact, this is what allows us to reliably warn about upcoming breaking changes. * **APIs starting with `unstable_`.** These are provided as experimental features whose APIs we are not yet confident in. By releasing these with an `unstable_` prefix, we can iterate faster and get to a stable API sooner. -* **Alpha and canary versions of React.** We provide alpha versions of React as a way to test new features early, but we need the flexibility to make changes based on what we learn in the alpha period. If you use these versions, note that APIs may change before the stable release. +* **Alpha and Canary versions of React.** We provide alpha versions of React as a way to test new features early, but we need the flexibility to make changes based on what we learn in the alpha period. If you use these versions, note that APIs may change before the stable release. * **Undocumented APIs and internal data structures.** If you access internal property names like `__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED` or `__reactInternalInstance$uk43rzhitjg`, there is no warranty. You are on your own. This policy is designed to be pragmatic: certainly, we don't want to cause headaches for you. If we bumped the major version for all of these changes, we would end up releasing more major versions and ultimately causing more versioning pain for the community. It would also mean that we can't make progress in improving React as fast as we'd like. diff --git a/src/content/learn/add-react-to-an-existing-project.md b/src/content/learn/add-react-to-an-existing-project.md index 47eacb70c..4b7098bd6 100644 --- a/src/content/learn/add-react-to-an-existing-project.md +++ b/src/content/learn/add-react-to-an-existing-project.md @@ -67,7 +67,7 @@ npm install react react-dom ``` -```js index.js active +```js src/index.js active import { createRoot } from 'react-dom/client'; // Clear the existing HTML content @@ -131,7 +131,7 @@ root.render(

Hello, world

); ``` -```js index.js active +```js src/index.js active import { createRoot } from 'react-dom/client'; function NavigationBar() { diff --git a/src/content/learn/adding-interactivity.md b/src/content/learn/adding-interactivity.md index 501c9f620..d1359d05a 100644 --- a/src/content/learn/adding-interactivity.md +++ b/src/content/learn/adding-interactivity.md @@ -134,7 +134,7 @@ export default function Gallery() { } ``` -```js data.js +```js src/data.js export const sculptureList = [{ name: 'Homenaje a la Neurocirugía', artist: 'Marta Colvin Andrade', diff --git a/src/content/learn/choosing-the-state-structure.md b/src/content/learn/choosing-the-state-structure.md index 49e11a22f..c3218589a 100644 --- a/src/content/learn/choosing-the-state-structure.md +++ b/src/content/learn/choosing-the-state-structure.md @@ -612,7 +612,7 @@ export default function TravelPlan() { } ``` -```js places.js active +```js src/places.js active export const initialTravelPlan = { id: 0, title: '(Root)', @@ -868,7 +868,7 @@ export default function TravelPlan() { } ``` -```js places.js active +```js src/places.js active export const initialTravelPlan = { 0: { id: 0, @@ -1204,7 +1204,7 @@ function PlaceTree({ id, parentId, placesById, onComplete }) { } ``` -```js places.js +```js src/places.js export const initialTravelPlan = { 0: { id: 0, @@ -1543,7 +1543,7 @@ function PlaceTree({ id, parentId, placesById, onComplete }) { } ``` -```js places.js +```js src/places.js export const initialTravelPlan = { 0: { id: 0, @@ -1841,7 +1841,7 @@ This `Clock` component receives two props: `color` and `time`. When you select a -```js Clock.js active +```js src/Clock.js active import { useState } from 'react'; export default function Clock(props) { @@ -1854,7 +1854,7 @@ export default function Clock(props) { } ``` -```js App.js hidden +```js src/App.js hidden import { useState, useEffect } from 'react'; import Clock from './Clock.js'; @@ -1896,7 +1896,7 @@ The issue is that this component has `color` state initialized with the initial -```js Clock.js active +```js src/Clock.js active import { useState } from 'react'; export default function Clock(props) { @@ -1908,7 +1908,7 @@ export default function Clock(props) { } ``` -```js App.js hidden +```js src/App.js hidden import { useState, useEffect } from 'react'; import Clock from './Clock.js'; @@ -1948,7 +1948,7 @@ Or, using the destructuring syntax: -```js Clock.js active +```js src/Clock.js active import { useState } from 'react'; export default function Clock({ color, time }) { @@ -1960,7 +1960,7 @@ export default function Clock({ color, time }) { } ``` -```js App.js hidden +```js src/App.js hidden import { useState, useEffect } from 'react'; import Clock from './Clock.js'; @@ -2010,7 +2010,7 @@ Is any state in this example redundant? -```js App.js +```js src/App.js import { useState } from 'react'; import AddItem from './AddItem.js'; import PackingList from './PackingList.js'; @@ -2078,7 +2078,7 @@ export default function TravelPlan() { } ``` -```js AddItem.js hidden +```js src/AddItem.js hidden import { useState } from 'react'; export default function AddItem({ onAddItem }) { @@ -2099,7 +2099,7 @@ export default function AddItem({ onAddItem }) { } ``` -```js PackingList.js hidden +```js src/PackingList.js hidden import { useState } from 'react'; export default function PackingList({ @@ -2149,7 +2149,7 @@ Although you could carefully change each event handler to update the `total` and -```js App.js +```js src/App.js import { useState } from 'react'; import AddItem from './AddItem.js'; import PackingList from './PackingList.js'; @@ -2213,7 +2213,7 @@ export default function TravelPlan() { } ``` -```js AddItem.js hidden +```js src/AddItem.js hidden import { useState } from 'react'; export default function AddItem({ onAddItem }) { @@ -2234,7 +2234,7 @@ export default function AddItem({ onAddItem }) { } ``` -```js PackingList.js hidden +```js src/PackingList.js hidden import { useState } from 'react'; export default function PackingList({ @@ -2290,7 +2290,7 @@ This code works, but there is a minor UI glitch. When you press "Star" or "Unsta -```js App.js +```js src/App.js import { useState } from 'react'; import { initialLetters } from './data.js'; import Letter from './Letter.js'; @@ -2337,7 +2337,7 @@ export default function MailClient() { } ``` -```js Letter.js +```js src/Letter.js export default function Letter({ letter, isHighlighted, @@ -2367,7 +2367,7 @@ export default function Letter({ } ``` -```js data.js +```js src/data.js export const initialLetters = [{ id: 0, subject: 'Ready for adventure?', @@ -2399,7 +2399,7 @@ To fix the issue, remove the duplication from state. Instead of storing *the let -```js App.js +```js src/App.js import { useState } from 'react'; import { initialLetters } from './data.js'; import Letter from './Letter.js'; @@ -2446,7 +2446,7 @@ export default function MailClient() { } ``` -```js Letter.js +```js src/Letter.js export default function Letter({ letter, isHighlighted, @@ -2476,7 +2476,7 @@ export default function Letter({ } ``` -```js data.js +```js src/data.js export const initialLetters = [{ id: 0, subject: 'Ready for adventure?', @@ -2516,7 +2516,7 @@ Instead of a single selected ID, you might want to hold an array or a [Set](http -```js App.js +```js src/App.js import { useState } from 'react'; import { letters } from './data.js'; import Letter from './Letter.js'; @@ -2559,7 +2559,7 @@ export default function MailClient() { } ``` -```js Letter.js +```js src/Letter.js export default function Letter({ letter, onToggle, @@ -2584,7 +2584,7 @@ export default function Letter({ } ``` -```js data.js +```js src/data.js export const letters = [{ id: 0, subject: 'Ready for adventure?', @@ -2615,7 +2615,7 @@ Instead of a single `selectedId`, keep a `selectedIds` *array* in state. For exa -```js App.js +```js src/App.js import { useState } from 'react'; import { letters } from './data.js'; import Letter from './Letter.js'; @@ -2667,7 +2667,7 @@ export default function MailClient() { } ``` -```js Letter.js +```js src/Letter.js export default function Letter({ letter, onToggle, @@ -2692,7 +2692,7 @@ export default function Letter({ } ``` -```js data.js +```js src/data.js export const letters = [{ id: 0, subject: 'Ready for adventure?', @@ -2723,7 +2723,7 @@ To fix this, you can hold a [Set](https://developer.mozilla.org/en-US/docs/Web/J -```js App.js +```js src/App.js import { useState } from 'react'; import { letters } from './data.js'; import Letter from './Letter.js'; @@ -2772,7 +2772,7 @@ export default function MailClient() { } ``` -```js Letter.js +```js src/Letter.js export default function Letter({ letter, onToggle, @@ -2797,7 +2797,7 @@ export default function Letter({ } ``` -```js data.js +```js src/data.js export const letters = [{ id: 0, subject: 'Ready for adventure?', diff --git a/src/content/learn/conditional-rendering.md b/src/content/learn/conditional-rendering.md index ce025c057..2f34a13b1 100644 --- a/src/content/learn/conditional-rendering.md +++ b/src/content/learn/conditional-rendering.md @@ -626,7 +626,11 @@ export default function PackingList() { 要注意的是你必須寫成 `importance > 0 && ...` 而不是 `importance && ...` ,這樣如果 `importance` 的值為 `0` 時,才不會把 `0` 做為結果 render 出來。 +<<<<<<< HEAD 解答中為了在 name 和 importance 標籤之間插入一個空格,使用了兩段不同的條件。你也可以使用帶有空格前綴的 fragment: `importance > 0 && <> ...`,或是直接在 `` 內部增加一個空格: `importance > 0 && ...`。 +======= +In this solution, two separate conditions are used to insert a space between the name and the importance label. Alternatively, you could use a Fragment with a leading space: `importance > 0 && <> ...` or add a space immediately inside the ``: `importance > 0 && ...`. +>>>>>>> 303ecae3dd4c7b570cf18e0115b94188f6aad5a1 diff --git a/src/content/learn/describing-the-ui.md b/src/content/learn/describing-the-ui.md index f5c936b6e..34b908727 100644 --- a/src/content/learn/describing-the-ui.md +++ b/src/content/learn/describing-the-ui.md @@ -72,7 +72,7 @@ img { margin: 0 10px 10px 0; height: 90px; } -```js App.js hidden +```js src/App.js hidden import Gallery from './Gallery.js'; export default function App() { @@ -82,7 +82,7 @@ export default function App() { } ``` -```js Gallery.js active +```js src/Gallery.js active import Profile from './Profile.js'; export default function Gallery() { @@ -97,7 +97,7 @@ export default function Gallery() { } ``` -```js Profile.js +```js src/Profile.js export default function Profile() { return ( -```js App.js +```js src/App.js import { people } from './data.js'; import { getImageUrl } from './utils.js'; @@ -405,7 +405,7 @@ export default function List() { } ``` -```js data.js +```js src/data.js export const people = [{ id: 0, name: 'Creola Katherine Johnson', @@ -439,7 +439,7 @@ export const people = [{ }]; ``` -```js utils.js +```js src/utils.js export function getImageUrl(person) { return ( 'https://i.imgur.com/' + @@ -538,12 +538,27 @@ React 使用 tree 來建模 component 和 module 之間的關係。 React render tree 是 component 之間父子關係的表示。 +<<<<<<< HEAD +======= + +An example React render tree. + + +>>>>>>> 303ecae3dd4c7b570cf18e0115b94188f6aad5a1 一個 React render tree 範例。 +<<<<<<< HEAD 靠近 tree 頂部、靠近 root component 的 component 被視為 top-level component。沒有 child component 的 component 是 leaf component。這種 component 分類對於理解 data flow 和 rendering 效能很有用。 +======= + + +An example module dependency tree. + + +>>>>>>> 303ecae3dd4c7b570cf18e0115b94188f6aad5a1 對 JavaScript module 之間的關係進行建模是了解應用程式的另一種有用方法。 我們稱之為 module dependency tree。 diff --git a/src/content/learn/escape-hatches.md b/src/content/learn/escape-hatches.md index 32dfbdee7..8e5c0c9d0 100644 --- a/src/content/learn/escape-hatches.md +++ b/src/content/learn/escape-hatches.md @@ -163,7 +163,7 @@ export default function ChatRoom() { } ``` -```js chat.js +```js src/chat.js export function createConnection() { // 真正在實作時會實際連線到伺服器 return { @@ -281,7 +281,7 @@ export default function App() { } ``` -```js chat.js +```js src/chat.js export function createConnection(serverUrl, roomId) { // 真正在實作時會實際連線到伺服器 return { @@ -395,7 +395,7 @@ export default function App() { } ``` -```js chat.js +```js src/chat.js export function createConnection(serverUrl, roomId) { // 真正在實作會實際連線到伺服器 let connectedCallback; @@ -424,7 +424,7 @@ export function createConnection(serverUrl, roomId) { } ``` -```js notifications.js +```js src/notifications.js import Toastify from 'toastify-js'; import 'toastify-js/src/toastify.css'; @@ -528,7 +528,7 @@ export default function App() { } ``` -```js chat.js +```js src/chat.js export function createConnection(serverUrl, roomId) { // 真正在實作時會實際連線到伺服器 let connectedCallback; @@ -557,7 +557,7 @@ export function createConnection(serverUrl, roomId) { } ``` -```js notifications.js hidden +```js src/notifications.js hidden import Toastify from 'toastify-js'; import 'toastify-js/src/toastify.css'; @@ -647,7 +647,7 @@ export default function App() { } ``` -```js chat.js +```js src/chat.js export function createConnection({ serverUrl, roomId }) { // 真正在實作時會實際連線到伺服器 return { @@ -721,7 +721,7 @@ export default function App() { } ``` -```js chat.js +```js src/chat.js export function createConnection({ serverUrl, roomId }) { // 真正在實作時會實際連線到伺服器 return { @@ -797,7 +797,7 @@ function Dot({ position, opacity }) { } ``` -```js usePointerPosition.js +```js src/usePointerPosition.js import { useState, useEffect } from 'react'; export function usePointerPosition() { @@ -813,7 +813,7 @@ export function usePointerPosition() { } ``` -```js useDelayedValue.js +```js src/useDelayedValue.js import { useState, useEffect } from 'react'; export function useDelayedValue(value, delay) { diff --git a/src/content/learn/extracting-state-logic-into-a-reducer.md b/src/content/learn/extracting-state-logic-into-a-reducer.md index 012a5c3f9..5c08c0123 100644 --- a/src/content/learn/extracting-state-logic-into-a-reducer.md +++ b/src/content/learn/extracting-state-logic-into-a-reducer.md @@ -23,7 +23,7 @@ As your components grow in complexity, it can get harder to see at a glance all -```js App.js +```js src/App.js import { useState } from 'react'; import AddTask from './AddTask.js'; import TaskList from './TaskList.js'; @@ -79,7 +79,7 @@ const initialTasks = [ ]; ``` -```js AddTask.js hidden +```js src/AddTask.js hidden import { useState } from 'react'; export default function AddTask({onAddTask}) { @@ -103,7 +103,7 @@ export default function AddTask({onAddTask}) { } ``` -```js TaskList.js hidden +```js src/TaskList.js hidden import { useState } from 'react'; export default function TaskList({tasks, onChangeTask, onDeleteTask}) { @@ -398,7 +398,7 @@ You could even use the `reduce()` method with an `initialState` and an array of -```js index.js active +```js src/index.js active import tasksReducer from './tasksReducer.js'; let initialState = []; @@ -415,7 +415,7 @@ const output = document.getElementById('output'); output.textContent = JSON.stringify(finalState, null, 2); ``` -```js tasksReducer.js +```js src/tasksReducer.js export default function tasksReducer(tasks, action) { switch (action.type) { case 'added': { @@ -493,7 +493,7 @@ Now it's fully wired up! Here, the reducer is declared at the bottom of the comp -```js App.js +```js src/App.js import { useReducer } from 'react'; import AddTask from './AddTask.js'; import TaskList from './TaskList.js'; @@ -574,7 +574,7 @@ const initialTasks = [ ]; ``` -```js AddTask.js hidden +```js src/AddTask.js hidden import { useState } from 'react'; export default function AddTask({onAddTask}) { @@ -598,7 +598,7 @@ export default function AddTask({onAddTask}) { } ``` -```js TaskList.js hidden +```js src/TaskList.js hidden import { useState } from 'react'; export default function TaskList({tasks, onChangeTask, onDeleteTask}) { @@ -678,7 +678,7 @@ If you want, you can even move the reducer to a different file: -```js App.js +```js src/App.js import { useReducer } from 'react'; import AddTask from './AddTask.js'; import TaskList from './TaskList.js'; @@ -730,7 +730,7 @@ const initialTasks = [ ]; ``` -```js tasksReducer.js +```js src/tasksReducer.js export default function tasksReducer(tasks, action) { switch (action.type) { case 'added': { @@ -762,7 +762,7 @@ export default function tasksReducer(tasks, action) { } ``` -```js AddTask.js hidden +```js src/AddTask.js hidden import { useState } from 'react'; export default function AddTask({onAddTask}) { @@ -786,7 +786,7 @@ export default function AddTask({onAddTask}) { } ``` -```js TaskList.js hidden +```js src/TaskList.js hidden import { useState } from 'react'; export default function TaskList({tasks, onChangeTask, onDeleteTask}) { @@ -889,7 +889,7 @@ Just like with [updating objects](/learn/updating-objects-in-state#write-concise -```js App.js +```js src/App.js import { useImmerReducer } from 'use-immer'; import AddTask from './AddTask.js'; import TaskList from './TaskList.js'; @@ -964,7 +964,7 @@ const initialTasks = [ ]; ``` -```js AddTask.js hidden +```js src/AddTask.js hidden import { useState } from 'react'; export default function AddTask({onAddTask}) { @@ -988,7 +988,7 @@ export default function AddTask({onAddTask}) { } ``` -```js TaskList.js hidden +```js src/TaskList.js hidden import { useState } from 'react'; export default function TaskList({tasks, onChangeTask, onDeleteTask}) { @@ -1126,7 +1126,7 @@ This means that your action object should have a `type: 'changed_selection'`. Yo -```js App.js +```js src/App.js import { useReducer } from 'react'; import Chat from './Chat.js'; import ContactList from './ContactList.js'; @@ -1160,7 +1160,7 @@ const contacts = [ ]; ``` -```js messengerReducer.js +```js src/messengerReducer.js export const initialState = { selectedId: 0, message: 'Hello', @@ -1188,7 +1188,7 @@ export function messengerReducer(state, action) { } ``` -```js ContactList.js +```js src/ContactList.js export default function ContactList({contacts, selectedId, dispatch}) { return (
@@ -1209,7 +1209,7 @@ export default function ContactList({contacts, selectedId, dispatch}) { } ``` -```js Chat.js +```js src/Chat.js import { useState } from 'react'; export default function Chat({contact, message, dispatch}) { @@ -1276,7 +1276,7 @@ Here is the example updated to dispatch the corresponding messages: -```js App.js +```js src/App.js import { useReducer } from 'react'; import Chat from './Chat.js'; import ContactList from './ContactList.js'; @@ -1310,7 +1310,7 @@ const contacts = [ ]; ``` -```js messengerReducer.js +```js src/messengerReducer.js export const initialState = { selectedId: 0, message: 'Hello', @@ -1338,7 +1338,7 @@ export function messengerReducer(state, action) { } ``` -```js ContactList.js +```js src/ContactList.js export default function ContactList({contacts, selectedId, dispatch}) { return (
@@ -1362,7 +1362,7 @@ export default function ContactList({contacts, selectedId, dispatch}) { } ``` -```js Chat.js +```js src/Chat.js import { useState } from 'react'; export default function Chat({contact, message, dispatch}) { @@ -1420,7 +1420,7 @@ Currently, pressing "Send" doesn't do anything. Add an event handler to the "Sen -```js App.js +```js src/App.js import { useReducer } from 'react'; import Chat from './Chat.js'; import ContactList from './ContactList.js'; @@ -1454,7 +1454,7 @@ const contacts = [ ]; ``` -```js messengerReducer.js +```js src/messengerReducer.js export const initialState = { selectedId: 0, message: 'Hello', @@ -1482,7 +1482,7 @@ export function messengerReducer(state, action) { } ``` -```js ContactList.js +```js src/ContactList.js export default function ContactList({contacts, selectedId, dispatch}) { return (
@@ -1506,7 +1506,7 @@ export default function ContactList({contacts, selectedId, dispatch}) { } ``` -```js Chat.js active +```js src/Chat.js active import { useState } from 'react'; export default function Chat({contact, message, dispatch}) { @@ -1559,7 +1559,7 @@ There are a couple of ways you could do it in the "Send" button event handler. O -```js App.js +```js src/App.js import { useReducer } from 'react'; import Chat from './Chat.js'; import ContactList from './ContactList.js'; @@ -1593,7 +1593,7 @@ const contacts = [ ]; ``` -```js messengerReducer.js +```js src/messengerReducer.js export const initialState = { selectedId: 0, message: 'Hello', @@ -1621,7 +1621,7 @@ export function messengerReducer(state, action) { } ``` -```js ContactList.js +```js src/ContactList.js export default function ContactList({contacts, selectedId, dispatch}) { return (
@@ -1645,7 +1645,7 @@ export default function ContactList({contacts, selectedId, dispatch}) { } ``` -```js Chat.js active +```js src/Chat.js active import { useState } from 'react'; export default function Chat({contact, message, dispatch}) { @@ -1707,7 +1707,7 @@ However, _from the user's perspective_, sending a message is a different action -```js App.js +```js src/App.js import { useReducer } from 'react'; import Chat from './Chat.js'; import ContactList from './ContactList.js'; @@ -1741,7 +1741,7 @@ const contacts = [ ]; ``` -```js messengerReducer.js active +```js src/messengerReducer.js active export const initialState = { selectedId: 0, message: 'Hello', @@ -1775,7 +1775,7 @@ export function messengerReducer(state, action) { } ``` -```js ContactList.js +```js src/ContactList.js export default function ContactList({contacts, selectedId, dispatch}) { return (
@@ -1799,7 +1799,7 @@ export default function ContactList({contacts, selectedId, dispatch}) { } ``` -```js Chat.js active +```js src/Chat.js active import { useState } from 'react'; export default function Chat({contact, message, dispatch}) { @@ -1904,7 +1904,7 @@ The `[key]: value` [computed property](https://developer.mozilla.org/en-US/docs/ -```js App.js +```js src/App.js import { useReducer } from 'react'; import Chat from './Chat.js'; import ContactList from './ContactList.js'; @@ -1938,7 +1938,7 @@ const contacts = [ ]; ``` -```js messengerReducer.js +```js src/messengerReducer.js export const initialState = { selectedId: 0, message: 'Hello', @@ -1972,7 +1972,7 @@ export function messengerReducer(state, action) { } ``` -```js ContactList.js +```js src/ContactList.js export default function ContactList({contacts, selectedId, dispatch}) { return (
@@ -1996,7 +1996,7 @@ export default function ContactList({contacts, selectedId, dispatch}) { } ``` -```js Chat.js +```js src/Chat.js import { useState } from 'react'; export default function Chat({contact, message, dispatch}) { @@ -2081,7 +2081,7 @@ Here is the complete solution: -```js App.js +```js src/App.js import { useReducer } from 'react'; import Chat from './Chat.js'; import ContactList from './ContactList.js'; @@ -2115,7 +2115,7 @@ const contacts = [ ]; ``` -```js messengerReducer.js +```js src/messengerReducer.js export const initialState = { selectedId: 0, messages: { @@ -2158,7 +2158,7 @@ export function messengerReducer(state, action) { } ``` -```js ContactList.js +```js src/ContactList.js export default function ContactList({contacts, selectedId, dispatch}) { return (
@@ -2182,7 +2182,7 @@ export default function ContactList({contacts, selectedId, dispatch}) { } ``` -```js Chat.js +```js src/Chat.js import { useState } from 'react'; export default function Chat({contact, message, dispatch}) { @@ -2269,7 +2269,7 @@ Recall that a reducer function takes two arguments--the current state and the ac -```js App.js +```js src/App.js import { useReducer } from './MyReact.js'; import Chat from './Chat.js'; import ContactList from './ContactList.js'; @@ -2303,7 +2303,7 @@ const contacts = [ ]; ``` -```js messengerReducer.js +```js src/messengerReducer.js export const initialState = { selectedId: 0, messages: { @@ -2346,7 +2346,7 @@ export function messengerReducer(state, action) { } ``` -```js MyReact.js active +```js src/MyReact.js active import { useState } from 'react'; export function useReducer(reducer, initialState) { @@ -2358,7 +2358,7 @@ export function useReducer(reducer, initialState) { } ``` -```js ContactList.js hidden +```js src/ContactList.js hidden export default function ContactList({contacts, selectedId, dispatch}) { return (
@@ -2382,7 +2382,7 @@ export default function ContactList({contacts, selectedId, dispatch}) { } ``` -```js Chat.js hidden +```js src/Chat.js hidden import { useState } from 'react'; export default function Chat({contact, message, dispatch}) { @@ -2443,7 +2443,7 @@ Dispatching an action calls a reducer with the current state and the action, and -```js App.js +```js src/App.js import { useReducer } from './MyReact.js'; import Chat from './Chat.js'; import ContactList from './ContactList.js'; @@ -2477,7 +2477,7 @@ const contacts = [ ]; ``` -```js messengerReducer.js +```js src/messengerReducer.js export const initialState = { selectedId: 0, messages: { @@ -2520,7 +2520,7 @@ export function messengerReducer(state, action) { } ``` -```js MyReact.js active +```js src/MyReact.js active import { useState } from 'react'; export function useReducer(reducer, initialState) { @@ -2535,7 +2535,7 @@ export function useReducer(reducer, initialState) { } ``` -```js ContactList.js hidden +```js src/ContactList.js hidden export default function ContactList({contacts, selectedId, dispatch}) { return (
@@ -2559,7 +2559,7 @@ export default function ContactList({contacts, selectedId, dispatch}) { } ``` -```js Chat.js hidden +```js src/Chat.js hidden import { useState } from 'react'; export default function Chat({contact, message, dispatch}) { diff --git a/src/content/learn/importing-and-exporting-components.md b/src/content/learn/importing-and-exporting-components.md index 3a39c36db..b458ef402 100644 --- a/src/content/learn/importing-and-exporting-components.md +++ b/src/content/learn/importing-and-exporting-components.md @@ -66,7 +66,7 @@ Here both `Profile` and `Gallery` have been moved out of `App.js` into a new fil -```js App.js +```js src/App.js import Gallery from './Gallery.js'; export default function App() { @@ -76,7 +76,7 @@ export default function App() { } ``` -```js Gallery.js +```js src/Gallery.js function Profile() { return ( -```js App.js +```js src/App.js import Gallery from './Gallery.js'; import { Profile } from './Gallery.js'; @@ -194,7 +194,7 @@ export default function App() { } ``` -```js Gallery.js +```js src/Gallery.js export function Profile() { return ( -```js App.js +```js src/App.js import Gallery from './Gallery.js'; import { Profile } from './Gallery.js'; @@ -281,7 +281,7 @@ export default function App() { } ``` -```js Gallery.js active +```js src/Gallery.js active // Move me to Profile.js! export function Profile() { return ( @@ -304,7 +304,7 @@ export default function Gallery() { } ``` -```js Profile.js +```js src/Profile.js ``` ```css @@ -321,7 +321,7 @@ This is the solution with named exports: -```js App.js +```js src/App.js import Gallery from './Gallery.js'; import { Profile } from './Profile.js'; @@ -335,7 +335,7 @@ export default function App() { } ``` -```js Gallery.js +```js src/Gallery.js import { Profile } from './Profile.js'; export default function Gallery() { @@ -350,7 +350,7 @@ export default function Gallery() { } ``` -```js Profile.js +```js src/Profile.js export function Profile() { return ( -```js App.js +```js src/App.js import Gallery from './Gallery.js'; import Profile from './Profile.js'; @@ -385,7 +385,7 @@ export default function App() { } ``` -```js Gallery.js +```js src/Gallery.js import Profile from './Profile.js'; export default function Gallery() { @@ -400,7 +400,7 @@ export default function Gallery() { } ``` -```js Profile.js +```js src/Profile.js export default function Profile() { return ( div > div { padding: 20px; } -```js App.js +```js src/App.js import { getImageUrl } from './utils.js' const person = { @@ -561,7 +561,7 @@ export default function TodoList() { } ``` -```js utils.js +```js src/utils.js export function getImageUrl(person) { return ( 'https://i.imgur.com/' + diff --git a/src/content/learn/keeping-components-pure.md b/src/content/learn/keeping-components-pure.md index 14ffce30d..39ee6741a 100644 --- a/src/content/learn/keeping-components-pure.md +++ b/src/content/learn/keeping-components-pure.md @@ -49,7 +49,7 @@ React 就是圍繞這個概念設計的。**React 假設你編寫的每個函式 -```js App.js +```js src/App.js function Recipe({ drinkers }) { return (
    @@ -243,7 +243,7 @@ Render 是一種*計算* ,它不應該嘗試「做」事情。你能用不同 -```js Clock.js active +```js src/Clock.js active export default function Clock({ time }) { let hours = time.getHours(); if (hours >= 0 && hours <= 6) { @@ -259,7 +259,7 @@ export default function Clock({ time }) { } ``` -```js App.js hidden +```js src/App.js hidden import { useState, useEffect } from 'react'; import Clock from './Clock.js'; @@ -305,7 +305,7 @@ body > * { -```js Clock.js active +```js src/Clock.js active export default function Clock({ time }) { let hours = time.getHours(); let className; @@ -322,7 +322,7 @@ export default function Clock({ time }) { } ``` -```js App.js hidden +```js src/App.js hidden import { useState, useEffect } from 'react'; import Clock from './Clock.js'; @@ -380,7 +380,7 @@ body > * { -```js Profile.js +```js src/Profile.js import Panel from './Panel.js'; import { getImageUrl } from './utils.js'; @@ -413,7 +413,7 @@ function Avatar() { } ``` -```js Panel.js hidden +```js src/Panel.js hidden import { useState } from 'react'; export default function Panel({ children }) { @@ -429,7 +429,7 @@ export default function Panel({ children }) { } ``` -```js App.js +```js src/App.js import Profile from './Profile.js'; export default function App() { @@ -448,7 +448,7 @@ export default function App() { } ``` -```js utils.js hidden +```js src/utils.js hidden export function getImageUrl(person, size = 's') { return ( 'https://i.imgur.com/' + @@ -481,7 +481,7 @@ h1 { margin: 5px; font-size: 18px; } -```js Profile.js active +```js src/Profile.js active import Panel from './Panel.js'; import { getImageUrl } from './utils.js'; @@ -511,7 +511,7 @@ function Avatar({ person }) { } ``` -```js Panel.js hidden +```js src/Panel.js hidden import { useState } from 'react'; export default function Panel({ children }) { @@ -527,7 +527,7 @@ export default function Panel({ children }) { } ``` -```js App.js +```js src/App.js import Profile from './Profile.js'; export default function App() { @@ -546,7 +546,7 @@ export default function App() { } ``` -```js utils.js hidden +```js src/utils.js hidden export function getImageUrl(person, size = 's') { return ( 'https://i.imgur.com/' + @@ -583,7 +583,7 @@ h1 { margin: 5px; font-size: 18px; } -```js StoryTray.js active +```js src/StoryTray.js active export default function StoryTray({ stories }) { stories.push({ id: 'create', @@ -602,7 +602,7 @@ export default function StoryTray({ stories }) { } ``` -```js App.js hidden +```js src/App.js hidden import { useState, useEffect } from 'react'; import StoryTray from './StoryTray.js'; @@ -683,7 +683,7 @@ li { -```js StoryTray.js active +```js src/StoryTray.js active export default function StoryTray({ stories }) { return (
      @@ -698,7 +698,7 @@ export default function StoryTray({ stories }) { } ``` -```js App.js hidden +```js src/App.js hidden import { useState, useEffect } from 'react'; import StoryTray from './StoryTray.js'; @@ -767,7 +767,7 @@ li { -```js StoryTray.js active +```js src/StoryTray.js active export default function StoryTray({ stories }) { // Copy the array! let storiesToDisplay = stories.slice(); @@ -790,7 +790,7 @@ export default function StoryTray({ stories }) { } ``` -```js App.js hidden +```js src/App.js hidden import { useState, useEffect } from 'react'; import StoryTray from './StoryTray.js'; diff --git a/src/content/learn/lifecycle-of-reactive-effects.md b/src/content/learn/lifecycle-of-reactive-effects.md index 5d9554a1a..3dc9a75f0 100644 --- a/src/content/learn/lifecycle-of-reactive-effects.md +++ b/src/content/learn/lifecycle-of-reactive-effects.md @@ -251,7 +251,7 @@ export default function App() { } ``` -```js chat.js +```js src/chat.js export function createConnection(serverUrl, roomId) { // A real implementation would actually connect to the server return { @@ -447,7 +447,7 @@ export default function App() { } ``` -```js chat.js +```js src/chat.js export function createConnection(serverUrl, roomId) { // A real implementation would actually connect to the server return { @@ -527,7 +527,7 @@ export default function App() { } ``` -```js chat.js +```js src/chat.js export function createConnection(serverUrl, roomId) { // A real implementation would actually connect to the server return { @@ -646,7 +646,7 @@ export default function App() { } ``` -```js chat.js +```js src/chat.js export function createConnection(serverUrl, roomId) { // A real implementation would actually connect to the server return { @@ -837,7 +837,7 @@ export default function App() { } ``` -```js chat.js +```js src/chat.js export function createConnection(serverUrl, roomId) { // A real implementation would actually connect to the server return { @@ -912,7 +912,7 @@ export default function App() { } ``` -```js chat.js +```js src/chat.js export function createConnection(serverUrl, roomId) { // A real implementation would actually connect to the server return { @@ -1329,7 +1329,7 @@ Suppressing the linter is always suspicious. Could this be a bug? -```js App.js +```js src/App.js import { useState } from 'react'; import ChatRoom from './ChatRoom.js'; import { @@ -1374,7 +1374,7 @@ export default function App() { } ``` -```js ChatRoom.js active +```js src/ChatRoom.js active import { useState, useEffect } from 'react'; export default function ChatRoom({ roomId, createConnection }) { @@ -1389,7 +1389,7 @@ export default function ChatRoom({ roomId, createConnection }) { } ``` -```js chat.js +```js src/chat.js export function createEncryptedConnection(roomId) { // A real implementation would actually connect to the server return { @@ -1427,7 +1427,7 @@ If you remove the linter suppression, you will see a lint error. The problem is -```js App.js +```js src/App.js import { useState } from 'react'; import ChatRoom from './ChatRoom.js'; import { @@ -1472,7 +1472,7 @@ export default function App() { } ``` -```js ChatRoom.js active +```js src/ChatRoom.js active import { useState, useEffect } from 'react'; export default function ChatRoom({ roomId, createConnection }) { @@ -1486,7 +1486,7 @@ export default function ChatRoom({ roomId, createConnection }) { } ``` -```js chat.js +```js src/chat.js export function createEncryptedConnection(roomId) { // A real implementation would actually connect to the server return { @@ -1522,7 +1522,7 @@ It is correct that `createConnection` is a dependency. However, this code is a b -```js App.js +```js src/App.js import { useState } from 'react'; import ChatRoom from './ChatRoom.js'; @@ -1560,7 +1560,7 @@ export default function App() { } ``` -```js ChatRoom.js active +```js src/ChatRoom.js active import { useState, useEffect } from 'react'; import { createEncryptedConnection, @@ -1581,7 +1581,7 @@ export default function ChatRoom({ roomId, isEncrypted }) { } ``` -```js chat.js +```js src/chat.js export function createEncryptedConnection(roomId) { // A real implementation would actually connect to the server return { @@ -1633,7 +1633,7 @@ If you have two independent synchronization processes, you need to write two sep -```js App.js +```js src/App.js import { useState, useEffect } from 'react'; import { fetchData } from './api.js'; @@ -1687,7 +1687,7 @@ export default function Page() { } ``` -```js api.js hidden +```js src/api.js hidden export function fetchData(url) { if (url === '/planets') { return fetchPlanets(); @@ -1782,7 +1782,7 @@ This is why it makes sense to describe them as two separate Effects. Here's an e -```js App.js +```js src/App.js import { useState, useEffect } from 'react'; import { fetchData } from './api.js'; @@ -1855,7 +1855,7 @@ export default function Page() { } ``` -```js api.js hidden +```js src/api.js hidden export function fetchData(url) { if (url === '/planets') { return fetchPlanets(); @@ -1945,7 +1945,7 @@ Instead, to reduce repetition, you can extract some logic into a custom Hook lik -```js App.js +```js src/App.js import { useState } from 'react'; import { useSelectOptions } from './useSelectOptions.js'; @@ -1991,7 +1991,7 @@ export default function Page() { } ``` -```js useSelectOptions.js +```js src/useSelectOptions.js import { useState, useEffect } from 'react'; import { fetchData } from './api.js'; @@ -2018,7 +2018,7 @@ export function useSelectOptions(url) { } ``` -```js api.js hidden +```js src/api.js hidden export function fetchData(url) { if (url === '/planets') { return fetchPlanets(); diff --git a/src/content/learn/managing-state.md b/src/content/learn/managing-state.md index c88ae3796..93bcc10fd 100644 --- a/src/content/learn/managing-state.md +++ b/src/content/learn/managing-state.md @@ -308,7 +308,7 @@ However, sometimes this is not what you want. In this chat app, typing a message -```js App.js +```js src/App.js import { useState } from 'react'; import Chat from './Chat.js'; import ContactList from './ContactList.js'; @@ -334,7 +334,7 @@ const contacts = [ ]; ``` -```js ContactList.js +```js src/ContactList.js export default function ContactList({ selectedContact, contacts, @@ -358,7 +358,7 @@ export default function ContactList({ } ``` -```js Chat.js +```js src/Chat.js import { useState } from 'react'; export default function Chat({ contact }) { @@ -403,7 +403,7 @@ React lets you override the default behavior, and *force* a component to reset i -```js App.js +```js src/App.js import { useState } from 'react'; import Chat from './Chat.js'; import ContactList from './ContactList.js'; @@ -429,7 +429,7 @@ const contacts = [ ]; ``` -```js ContactList.js +```js src/ContactList.js export default function ContactList({ selectedContact, contacts, @@ -453,7 +453,7 @@ export default function ContactList({ } ``` -```js Chat.js +```js src/Chat.js import { useState } from 'react'; export default function Chat({ contact }) { @@ -506,7 +506,7 @@ Components with many state updates spread across many event handlers can get ove -```js App.js +```js src/App.js import { useReducer } from 'react'; import AddTask from './AddTask.js'; import TaskList from './TaskList.js'; @@ -589,7 +589,7 @@ const initialTasks = [ ]; ``` -```js AddTask.js hidden +```js src/AddTask.js hidden import { useState } from 'react'; export default function AddTask({ onAddTask }) { @@ -610,7 +610,7 @@ export default function AddTask({ onAddTask }) { } ``` -```js TaskList.js hidden +```js src/TaskList.js hidden import { useState } from 'react'; export default function TaskList({ @@ -733,7 +733,7 @@ export default function Page() { } ``` -```js Section.js +```js src/Section.js import { useContext } from 'react'; import { LevelContext } from './LevelContext.js'; @@ -749,7 +749,7 @@ export default function Section({ children }) { } ``` -```js Heading.js +```js src/Heading.js import { useContext } from 'react'; import { LevelContext } from './LevelContext.js'; @@ -776,7 +776,7 @@ export default function Heading({ children }) { } ``` -```js LevelContext.js +```js src/LevelContext.js import { createContext } from 'react'; export const LevelContext = createContext(0); @@ -807,7 +807,7 @@ With this approach, a parent component with complex state manages it with a redu -```js App.js +```js src/App.js import AddTask from './AddTask.js'; import TaskList from './TaskList.js'; import { TasksProvider } from './TasksContext.js'; @@ -823,7 +823,7 @@ export default function TaskApp() { } ``` -```js TasksContext.js +```js src/TasksContext.js import { createContext, useContext, useReducer } from 'react'; const TasksContext = createContext(null); @@ -888,7 +888,7 @@ const initialTasks = [ ]; ``` -```js AddTask.js +```js src/AddTask.js import { useState, useContext } from 'react'; import { useTasksDispatch } from './TasksContext.js'; @@ -917,7 +917,7 @@ export default function AddTask({ onAddTask }) { let nextId = 3; ``` -```js TaskList.js +```js src/TaskList.js import { useState, useContext } from 'react'; import { useTasks, useTasksDispatch } from './TasksContext.js'; diff --git a/src/content/learn/manipulating-the-dom-with-refs.md b/src/content/learn/manipulating-the-dom-with-refs.md index 3e91a7694..3d5cbfd1d 100644 --- a/src/content/learn/manipulating-the-dom-with-refs.md +++ b/src/content/learn/manipulating-the-dom-with-refs.md @@ -1098,7 +1098,7 @@ You'll need `forwardRef` to opt into exposing a DOM node from your own component -```js App.js +```js src/App.js import SearchButton from './SearchButton.js'; import SearchInput from './SearchInput.js'; @@ -1114,7 +1114,7 @@ export default function Page() { } ``` -```js SearchButton.js +```js src/SearchButton.js export default function SearchButton() { return ( ; } ``` -```css styles.css +```css src/styles.css * { box-sizing: border-box; } @@ -362,11 +362,11 @@ You'll get this error: -/src/App.js: Adjacent JSX elements must be wrapped in an enclosing tag. Did you want a JSX fragment `<>...`? +/src/App.js: Adjacent JSX elements must be wrapped in an enclosing tag. Did you want a JSX Fragment `<>...`? -React components need to return a single JSX element and not multiple adjacent JSX elements like two buttons. To fix this you can use *fragments* (`<>` and ``) to wrap multiple adjacent JSX elements like this: +React components need to return a single JSX element and not multiple adjacent JSX elements like two buttons. To fix this you can use *Fragments* (`<>` and ``) to wrap multiple adjacent JSX elements like this: ```js {3-6} export default function Square() { @@ -455,7 +455,7 @@ export default function Board() { } ``` -```css styles.css +```css src/styles.css * { box-sizing: border-box; } @@ -627,7 +627,7 @@ Your updated code should look like this: -```js App.js +```js src/App.js function Square({ value }) { return ; } @@ -655,7 +655,7 @@ export default function Board() { } ``` -```css styles.css +```css src/styles.css * { box-sizing: border-box; } @@ -807,7 +807,7 @@ After you've made the above changes, your code will look like this: -```js App.js +```js src/App.js import { useState } from 'react'; function Square() { @@ -850,7 +850,7 @@ export default function Board() { } ``` -```css styles.css +```css src/styles.css * { box-sizing: border-box; } @@ -988,7 +988,7 @@ And your code should look like this: -```js App.js +```js src/App.js import { useState } from 'react'; function Square({ value }) { @@ -1019,7 +1019,7 @@ export default function Board() { } ``` -```css styles.css +```css src/styles.css * { box-sizing: border-box; } @@ -1228,7 +1228,7 @@ This is what your code should look like: -```js App.js +```js src/App.js import { useState } from 'react'; function Square({ value, onSquareClick }) { @@ -1270,7 +1270,7 @@ export default function Board() { } ``` -```css styles.css +```css src/styles.css * { box-sizing: border-box; } @@ -1422,7 +1422,7 @@ Now you can only add `X`'s or `O`'s to empty squares! Here is what your code sho -```js App.js +```js src/App.js import { useState } from 'react'; function Square({value, onSquareClick}) { @@ -1473,7 +1473,7 @@ export default function Board() { } ``` -```css styles.css +```css src/styles.css * { box-sizing: border-box; } @@ -1524,7 +1524,7 @@ body { Now that the players can take turns, you'll want to show when the game is won and there are no more turns to make. To do this you'll add a helper function called `calculateWinner` that takes an array of 9 squares, checks for a winner and returns `'X'`, `'O'`, or `null` as appropriate. Don't worry too much about the `calculateWinner` function; it's not specific to React: -```js App.js +```js src/App.js export default function Board() { //... } @@ -1594,7 +1594,7 @@ Congratulations! You now have a working tic-tac-toe game. And you've just learne -```js App.js +```js src/App.js import { useState } from 'react'; function Square({value, onSquareClick}) { @@ -1674,7 +1674,7 @@ function calculateWinner(squares) { } ``` -```css styles.css +```css src/styles.css * { box-sizing: border-box; } @@ -1872,7 +1872,7 @@ At this point, you've moved the state to live in the `Game` component, and the U -```js App.js +```js src/App.js import { useState } from 'react'; function Square({ value, onSquareClick }) { @@ -1970,7 +1970,7 @@ function calculateWinner(squares) { } ``` -```css styles.css +```css src/styles.css * { box-sizing: border-box; } @@ -2083,7 +2083,7 @@ You'll fix this error in the next section. -```js App.js +```js src/App.js import { useState } from 'react'; function Square({ value, onSquareClick }) { @@ -2199,7 +2199,7 @@ function calculateWinner(squares) { } ``` -```css styles.css +```css src/styles.css * { box-sizing: border-box; } @@ -2311,7 +2311,7 @@ const moves = history.map((squares, move) => { -```js App.js +```js src/App.js import { useState } from 'react'; function Square({ value, onSquareClick }) { @@ -2428,7 +2428,7 @@ function calculateWinner(squares) { ``` -```css styles.css +```css src/styles.css * { box-sizing: border-box; } @@ -2532,7 +2532,7 @@ If you click on any step in the game's history, the tic-tac-toe board should imm -```js App.js +```js src/App.js import { useState } from 'react'; function Square({value, onSquareClick}) { @@ -2652,7 +2652,7 @@ function calculateWinner(squares) { } ``` -```css styles.css +```css src/styles.css * { box-sizing: border-box; } @@ -2742,7 +2742,7 @@ Check out the final result here: -```js App.js +```js src/App.js import { useState } from 'react'; function Square({ value, onSquareClick }) { @@ -2860,7 +2860,7 @@ function calculateWinner(squares) { } ``` -```css styles.css +```css src/styles.css * { box-sizing: border-box; } diff --git a/src/content/learn/typescript.md b/src/content/learn/typescript.md index 04c0efc17..034ac0d46 100644 --- a/src/content/learn/typescript.md +++ b/src/content/learn/typescript.md @@ -55,7 +55,7 @@ Taking the [`MyButton` component](/learn#components) from the [Quick Start](/lea -```tsx App.tsx active +```tsx src/App.tsx active function MyButton({ title }: { title: string }) { return ( @@ -72,7 +72,7 @@ export default function MyApp() { } ``` -```js App.js hidden +```js src/App.js hidden import AppTSX from "./App.tsx"; export default App = AppTSX; ``` @@ -88,7 +88,7 @@ This inline syntax is the simplest way to provide types for a component, though -```tsx App.tsx active +```tsx src/App.tsx active interface MyButtonProps { /** The text to display inside the button */ title: string; @@ -112,7 +112,7 @@ export default function MyApp() { } ``` -```js App.js hidden +```js src/App.js hidden import AppTSX from "./App.tsx"; export default App = AppTSX; ``` @@ -170,7 +170,7 @@ The [`useReducer` Hook](/reference/react/useReducer) is a more complex Hook that -```tsx App.tsx active +```tsx src/App.tsx active import {useReducer} from 'react'; interface State { @@ -213,7 +213,7 @@ export default function App() { ``` -```js App.js hidden +```js src/App.js hidden import AppTSX from "./App.tsx"; export default App = AppTSX; ``` @@ -248,7 +248,7 @@ The type of the value provided by the context is inferred from the value passed -```tsx App.tsx active +```tsx src/App.tsx active import { createContext, useContext, useState } from 'react'; type Theme = "light" | "dark" | "system"; @@ -277,7 +277,7 @@ function MyComponent() { } ``` -```js App.js hidden +```js src/App.js hidden import AppTSX from "./App.tsx"; export default App = AppTSX; ``` @@ -381,7 +381,7 @@ When working with DOM events in React, the type of the event can often be inferr -```tsx App.tsx active +```tsx src/App.tsx active import { useState } from 'react'; export default function Form() { @@ -400,7 +400,7 @@ export default function Form() { } ``` -```js App.js hidden +```js src/App.js hidden import AppTSX from "./App.tsx"; export default App = AppTSX; ``` diff --git a/src/content/learn/understanding-your-ui-as-a-tree.md b/src/content/learn/understanding-your-ui-as-a-tree.md index 98f60cea8..f4528b346 100644 --- a/src/content/learn/understanding-your-ui-as-a-tree.md +++ b/src/content/learn/understanding-your-ui-as-a-tree.md @@ -39,7 +39,7 @@ Here is a React app that renders inspirational quotes. -```js App.js +```js src/App.js import FancyText from './FancyText'; import InspirationGenerator from './InspirationGenerator'; import Copyright from './Copyright'; @@ -57,7 +57,7 @@ export default function App() { ``` -```js FancyText.js +```js src/FancyText.js export default function FancyText({title, text}) { return title ?

      {text}

      @@ -65,7 +65,7 @@ export default function FancyText({title, text}) { } ``` -```js InspirationGenerator.js +```js src/InspirationGenerator.js import * as React from 'react'; import quotes from './quotes'; import FancyText from './FancyText'; @@ -86,13 +86,13 @@ export default function InspirationGenerator({children}) { } ``` -```js Copyright.js +```js src/Copyright.js export default function Copyright({year}) { return

      ©️ {year}

      ; } ``` -```js quotes.js +```js src/quotes.js export default [ "Don’t let yesterday take up too much of today.” — Will Rogers", "Ambition is putting a ladder against the sky.", @@ -149,7 +149,7 @@ We can update the app to conditionally render either an inspirational quote or c -```js App.js +```js src/App.js import FancyText from './FancyText'; import InspirationGenerator from './InspirationGenerator'; import Copyright from './Copyright'; @@ -167,7 +167,7 @@ export default function App() { ``` -```js FancyText.js +```js src/FancyText.js export default function FancyText({title, text}) { return title ?

      {text}

      @@ -175,13 +175,13 @@ export default function FancyText({title, text}) { } ``` -```js Color.js +```js src/Color.js export default function Color({value}) { return
      } ``` -```js InspirationGenerator.js +```js src/InspirationGenerator.js import * as React from 'react'; import inspirations from './inspirations'; import FancyText from './FancyText'; @@ -206,13 +206,13 @@ export default function InspirationGenerator({children}) { } ``` -```js Copyright.js +```js src/Copyright.js export default function Copyright({year}) { return

      ©️ {year}

      ; } ``` -```js inspirations.js +```js src/inspirations.js export default [ {type: 'quote', value: "Don’t let yesterday take up too much of today.” — Will Rogers"}, {type: 'color', value: "#B73636"}, diff --git a/src/content/learn/updating-arrays-in-state.md b/src/content/learn/updating-arrays-in-state.md index 45c6b70dc..ea861931e 100644 --- a/src/content/learn/updating-arrays-in-state.md +++ b/src/content/learn/updating-arrays-in-state.md @@ -1084,7 +1084,7 @@ In this example, all of the event handlers in `App.js` use mutation. As a result -```js App.js +```js src/App.js import { useState } from 'react'; import AddTodo from './AddTodo.js'; import TaskList from './TaskList.js'; @@ -1139,7 +1139,7 @@ export default function TaskApp() { } ``` -```js AddTodo.js +```js src/AddTodo.js import { useState } from 'react'; export default function AddTodo({ onAddTodo }) { @@ -1160,7 +1160,7 @@ export default function AddTodo({ onAddTodo }) { } ``` -```js TaskList.js +```js src/TaskList.js import { useState } from 'react'; export default function TaskList({ @@ -1247,7 +1247,7 @@ In `handleAddTodo`, you can use the array spread syntax. In `handleChangeTodo`, -```js App.js +```js src/App.js import { useState } from 'react'; import AddTodo from './AddTodo.js'; import TaskList from './TaskList.js'; @@ -1306,7 +1306,7 @@ export default function TaskApp() { } ``` -```js AddTodo.js +```js src/AddTodo.js import { useState } from 'react'; export default function AddTodo({ onAddTodo }) { @@ -1327,7 +1327,7 @@ export default function AddTodo({ onAddTodo }) { } ``` -```js TaskList.js +```js src/TaskList.js import { useState } from 'react'; export default function TaskList({ @@ -1417,7 +1417,7 @@ This is the same example as in the previous challenge. This time, fix the mutati -```js App.js +```js src/App.js import { useState } from 'react'; import { useImmer } from 'use-immer'; import AddTodo from './AddTodo.js'; @@ -1473,7 +1473,7 @@ export default function TaskApp() { } ``` -```js AddTodo.js +```js src/AddTodo.js import { useState } from 'react'; export default function AddTodo({ onAddTodo }) { @@ -1494,7 +1494,7 @@ export default function AddTodo({ onAddTodo }) { } ``` -```js TaskList.js +```js src/TaskList.js import { useState } from 'react'; export default function TaskList({ @@ -1599,7 +1599,7 @@ With Immer, you can write code in the mutative fashion, as long as you're only m -```js App.js +```js src/App.js import { useState } from 'react'; import { useImmer } from 'use-immer'; import AddTodo from './AddTodo.js'; @@ -1661,7 +1661,7 @@ export default function TaskApp() { } ``` -```js AddTodo.js +```js src/AddTodo.js import { useState } from 'react'; export default function AddTodo({ onAddTodo }) { @@ -1682,7 +1682,7 @@ export default function AddTodo({ onAddTodo }) { } ``` -```js TaskList.js +```js src/TaskList.js import { useState } from 'react'; export default function TaskList({ @@ -1787,7 +1787,7 @@ For example, in this version `handleAddTodo` is implemented by mutating the Imme -```js App.js +```js src/App.js import { useState } from 'react'; import { useImmer } from 'use-immer'; import AddTodo from './AddTodo.js'; @@ -1846,7 +1846,7 @@ export default function TaskApp() { } ``` -```js AddTodo.js +```js src/AddTodo.js import { useState } from 'react'; export default function AddTodo({ onAddTodo }) { @@ -1867,7 +1867,7 @@ export default function AddTodo({ onAddTodo }) { } ``` -```js TaskList.js +```js src/TaskList.js import { useState } from 'react'; export default function TaskList({ diff --git a/src/content/learn/updating-objects-in-state.md b/src/content/learn/updating-objects-in-state.md index 9289f2454..923e4e181 100644 --- a/src/content/learn/updating-objects-in-state.md +++ b/src/content/learn/updating-objects-in-state.md @@ -986,7 +986,7 @@ If something unexpected changes, there is a mutation. Find the mutation in `App. -```js App.js +```js src/App.js import { useState } from 'react'; import Background from './Background.js'; import Box from './Box.js'; @@ -1039,7 +1039,7 @@ export default function Canvas() { } ``` -```js Box.js +```js src/Box.js import { useState } from 'react'; export default function Box({ @@ -1102,7 +1102,7 @@ export default function Box({ } ``` -```js Background.js +```js src/Background.js export default function Background({ position }) { @@ -1136,7 +1136,7 @@ The fix is to remove the mutation from `handleMove`, and use the spread syntax t -```js App.js +```js src/App.js import { useState } from 'react'; import Background from './Background.js'; import Box from './Box.js'; @@ -1194,7 +1194,7 @@ export default function Canvas() { } ``` -```js Box.js +```js src/Box.js import { useState } from 'react'; export default function Box({ @@ -1257,7 +1257,7 @@ export default function Box({ } ``` -```js Background.js +```js src/Background.js export default function Background({ position }) { @@ -1291,7 +1291,7 @@ This is the same buggy example as in the previous challenge. This time, fix the -```js App.js +```js src/App.js import { useState } from 'react'; import { useImmer } from 'use-immer'; import Background from './Background.js'; @@ -1345,7 +1345,7 @@ export default function Canvas() { } ``` -```js Box.js +```js src/Box.js import { useState } from 'react'; export default function Box({ @@ -1408,7 +1408,7 @@ export default function Box({ } ``` -```js Background.js +```js src/Background.js export default function Background({ position }) { @@ -1458,7 +1458,7 @@ This is the solution rewritten with Immer. Notice how the event handlers are wri -```js App.js +```js src/App.js import { useImmer } from 'use-immer'; import Background from './Background.js'; import Box from './Box.js'; @@ -1512,7 +1512,7 @@ export default function Canvas() { } ``` -```js Box.js +```js src/Box.js import { useState } from 'react'; export default function Box({ @@ -1575,7 +1575,7 @@ export default function Box({ } ``` -```js Background.js +```js src/Background.js export default function Background({ position }) { diff --git a/src/content/learn/you-might-not-need-an-effect.md b/src/content/learn/you-might-not-need-an-effect.md index a3b33d3a7..66cdc3117 100644 --- a/src/content/learn/you-might-not-need-an-effect.md +++ b/src/content/learn/you-might-not-need-an-effect.md @@ -882,7 +882,7 @@ function NewTodo({ onAdd }) { } ``` -```js todos.js +```js src/todos.js let nextId = 0; export function createTodo(text, completed = false) { @@ -975,7 +975,7 @@ function NewTodo({ onAdd }) { } ``` -```js todos.js +```js src/todos.js let nextId = 0; export function createTodo(text, completed = false) { @@ -1061,7 +1061,7 @@ export default function TodoList() { } ``` -```js todos.js +```js src/todos.js let nextId = 0; let calls = 0; @@ -1144,7 +1144,7 @@ export default function TodoList() { } ``` -```js todos.js +```js src/todos.js let nextId = 0; let calls = 0; @@ -1233,7 +1233,7 @@ function NewTodo({ onAdd }) { } ``` -```js todos.js +```js src/todos.js let nextId = 0; let calls = 0; @@ -1278,7 +1278,7 @@ When you select a contact with the buttons at the top, the form resets to reflec -```js App.js hidden +```js src/App.js hidden import { useState } from 'react'; import ContactList from './ContactList.js'; import EditContact from './EditContact.js'; @@ -1330,7 +1330,7 @@ const initialContacts = [ ]; ``` -```js ContactList.js hidden +```js src/ContactList.js hidden export default function ContactList({ contacts, selectedId, @@ -1357,7 +1357,7 @@ export default function ContactList({ } ``` -```js EditContact.js active +```js src/EditContact.js active import { useState, useEffect } from 'react'; export default function EditContact({ savedContact, onSave }) { @@ -1442,7 +1442,7 @@ Split the `EditContact` component in two. Move all the form state into the inner -```js App.js hidden +```js src/App.js hidden import { useState } from 'react'; import ContactList from './ContactList.js'; import EditContact from './EditContact.js'; @@ -1494,7 +1494,7 @@ const initialContacts = [ ]; ``` -```js ContactList.js hidden +```js src/ContactList.js hidden export default function ContactList({ contacts, selectedId, @@ -1521,7 +1521,7 @@ export default function ContactList({ } ``` -```js EditContact.js active +```js src/EditContact.js active import { useState } from 'react'; export default function EditContact(props) { diff --git a/src/content/reference/react-dom/client/createRoot.md b/src/content/reference/react-dom/client/createRoot.md index d91bc20c6..afddb4177 100644 --- a/src/content/reference/react-dom/client/createRoot.md +++ b/src/content/reference/react-dom/client/createRoot.md @@ -153,7 +153,7 @@ Usually, you only need to run this code once at startup. It will: ``` -```js index.js active +```js src/index.js active import { createRoot } from 'react-dom/client'; import App from './App.js'; import './styles.css'; @@ -162,7 +162,7 @@ const root = createRoot(document.getElementById('root')); root.render(); ``` -```js App.js +```js src/App.js import { useState } from 'react'; export default function App() { @@ -232,7 +232,7 @@ Here, two different React components are rendered into two DOM nodes defined in ``` -```js index.js active +```js src/index.js active import './styles.css'; import { createRoot } from 'react-dom/client'; import { Comments, Navigation } from './Components.js'; @@ -246,7 +246,7 @@ const commentRoot = createRoot(commentDomNode); commentRoot.render(); ``` -```js Components.js +```js src/Components.js export function Navigation() { return (
        @@ -313,7 +313,7 @@ You can call `render` more than once on the same root. As long as the component -```js index.js active +```js src/index.js active import { createRoot } from 'react-dom/client'; import './styles.css'; import App from './App.js'; @@ -327,7 +327,7 @@ setInterval(() => { }, 1000); ``` -```js App.js +```js src/App.js export default function App({counter}) { return ( <> diff --git a/src/content/reference/react-dom/client/hydrateRoot.md b/src/content/reference/react-dom/client/hydrateRoot.md index cf77a81ac..c137cdda9 100644 --- a/src/content/reference/react-dom/client/hydrateRoot.md +++ b/src/content/reference/react-dom/client/hydrateRoot.md @@ -143,7 +143,7 @@ To hydrate your app, React will "attach" your components' logic to the initial g

        Hello, world!

        ``` -```js index.js active +```js src/index.js active import './styles.css'; import { hydrateRoot } from 'react-dom/client'; import App from './App.js'; @@ -154,7 +154,7 @@ hydrateRoot( ); ``` -```js App.js +```js src/App.js import { useState } from 'react'; export default function App() { @@ -248,7 +248,7 @@ To silence hydration warnings on an element, add `suppressHydrationWarning={true

        Current Date: 01/01/2020

        ``` -```js index.js +```js src/index.js import './styles.css'; import { hydrateRoot } from 'react-dom/client'; import App from './App.js'; @@ -256,7 +256,7 @@ import App from './App.js'; hydrateRoot(document.getElementById('root'), ); ``` -```js App.js active +```js src/App.js active export default function App() { return (

        @@ -286,7 +286,7 @@ If you intentionally need to render something different on the server and the cl

        Is Server

        ``` -```js index.js +```js src/index.js import './styles.css'; import { hydrateRoot } from 'react-dom/client'; import App from './App.js'; @@ -294,7 +294,7 @@ import App from './App.js'; hydrateRoot(document.getElementById('root'), ); ``` -```js App.js active +```js src/App.js active import { useState, useEffect } from "react"; export default function App() { @@ -340,7 +340,7 @@ If you call `root.render` at some point after hydration, and the component tree

        Hello, world! 0

        ``` -```js index.js active +```js src/index.js active import { hydrateRoot } from 'react-dom/client'; import './styles.css'; import App from './App.js'; @@ -357,7 +357,7 @@ setInterval(() => { }, 1000); ``` -```js App.js +```js src/App.js export default function App({counter}) { return ( <> diff --git a/src/content/reference/react-dom/components/common.md b/src/content/reference/react-dom/components/common.md index 78d2713bc..11719112e 100644 --- a/src/content/reference/react-dom/components/common.md +++ b/src/content/reference/react-dom/components/common.md @@ -771,7 +771,7 @@ In the above example, `style={{}}` is not a special syntax, but a regular `{}` o -```js App.js +```js src/App.js import Avatar from './Avatar.js'; const user = { @@ -785,7 +785,7 @@ export default function App() { } ``` -```js Avatar.js active +```js src/Avatar.js active export default function Avatar({ user }) { return ( +<<<<<<< HEAD ```js App.js +======= +```js src/App.js +>>>>>>> 303ecae3dd4c7b570cf18e0115b94188f6aad5a1 export default function Search() { function search(formData) { const query = formData.get("query"); @@ -146,7 +150,11 @@ Here, we use the `pending` property to indicate the form is submitting. +<<<<<<< HEAD ```js App.js +======= +```js src/App.js +>>>>>>> 303ecae3dd4c7b570cf18e0115b94188f6aad5a1 import { useFormStatus } from "react-dom"; import { submitForm } from "./actions.js"; @@ -172,7 +180,11 @@ export default function App() { } ``` +<<<<<<< HEAD ```js actions.js hidden +======= +```js src/actions.js hidden +>>>>>>> 303ecae3dd4c7b570cf18e0115b94188f6aad5a1 export async function submitForm(query) { await new Promise((res) => setTimeout(res, 1000)); } @@ -201,7 +213,11 @@ For example, when a user types a message into the form and hits the "Send" butto +<<<<<<< HEAD ```js App.js +======= +```js src/App.js +>>>>>>> 303ecae3dd4c7b570cf18e0115b94188f6aad5a1 import { useOptimistic, useState, useRef } from "react"; import { deliverMessage } from "./actions.js"; @@ -251,7 +267,11 @@ export default function App() { } ``` +<<<<<<< HEAD ```js actions.js +======= +```js src/actions.js +>>>>>>> 303ecae3dd4c7b570cf18e0115b94188f6aad5a1 export async function deliverMessage(message) { await new Promise((res) => setTimeout(res, 1000)); return message; @@ -282,7 +302,11 @@ In some cases the function called by a ``'s `action` prop throw an error. +<<<<<<< HEAD ```js App.js +======= +```js src/App.js +>>>>>>> 303ecae3dd4c7b570cf18e0115b94188f6aad5a1 import { ErrorBoundary } from "react-error-boundary"; export default function Search() { @@ -330,7 +354,11 @@ Displaying a form submission error message before the JavaScript bundle loads fo +<<<<<<< HEAD ```js App.js +======= +```js src/App.js +>>>>>>> 303ecae3dd4c7b570cf18e0115b94188f6aad5a1 import { useFormState } from "react-dom"; import { signUpNewUser } from "./api"; @@ -361,7 +389,11 @@ export default function Page() { } ``` +<<<<<<< HEAD ```js api.js hidden +======= +```js src/api.js hidden +>>>>>>> 303ecae3dd4c7b570cf18e0115b94188f6aad5a1 let emails = []; export async function signUpNewUser(newEmail) { @@ -396,7 +428,11 @@ When a user taps a specific button, the form is submitted, and a corresponding a +<<<<<<< HEAD ```js App.js +======= +```js src/App.js +>>>>>>> 303ecae3dd4c7b570cf18e0115b94188f6aad5a1 export default function Search() { function publish(formData) { const content = formData.get("content"); diff --git a/src/content/reference/react-dom/components/input.md b/src/content/reference/react-dom/components/input.md index 7328fddc9..b4db79839 100644 --- a/src/content/reference/react-dom/components/input.md +++ b/src/content/reference/react-dom/components/input.md @@ -34,7 +34,11 @@ To display an input, render the [built-in browser ``](https://developer.m +<<<<<<< HEAD React's extensions to the `formAction` prop are currently only available in React's canary and experimental channels. In stable releases of React `formAction` works only as a [built-in browser HTML component](https://react.dev/reference/react-dom/components#all-html-components). Learn more about [React's release channels here](/community/versioning-policy#all-release-channels). +======= +React's extensions to the `formAction` prop are currently only available in React's Canary and experimental channels. In stable releases of React `formAction` works only as a [built-in browser HTML component](https://react.dev/reference/react-dom/components#all-html-components). Learn more about [React's release channels here](/community/versioning-policy#all-release-channels). +>>>>>>> 303ecae3dd4c7b570cf18e0115b94188f6aad5a1 [`formAction`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input#formaction): A string or function. Overrides the parent `` for `type="submit"` and `type="image"`. When a URL is passed to `action` the form will behave like a standard HTML form. When a function is passed to `formAction` the function will handle the form submission. See [``](/reference/react-dom/components/form#props). diff --git a/src/content/reference/react-dom/components/textarea.md b/src/content/reference/react-dom/components/textarea.md index 5c742f293..2639fcd73 100644 --- a/src/content/reference/react-dom/components/textarea.md +++ b/src/content/reference/react-dom/components/textarea.md @@ -294,7 +294,7 @@ export default function MarkdownEditor() { } ``` -```js MarkdownPreview.js +```js src/MarkdownPreview.js import { Remarkable } from 'remarkable'; const md = new Remarkable(); diff --git a/src/content/reference/react-dom/createPortal.md b/src/content/reference/react-dom/createPortal.md index 006f78a9a..0107c20d3 100644 --- a/src/content/reference/react-dom/createPortal.md +++ b/src/content/reference/react-dom/createPortal.md @@ -137,7 +137,7 @@ In this example, the two containers have styles that disrupt the modal dialog, b -```js App.js active +```js src/App.js active import NoPortalExample from './NoPortalExample'; import PortalExample from './PortalExample'; @@ -155,7 +155,7 @@ export default function App() { } ``` -```js NoPortalExample.js +```js src/NoPortalExample.js import { useState } from 'react'; import ModalContent from './ModalContent.js'; @@ -174,7 +174,7 @@ export default function NoPortalExample() { } ``` -```js PortalExample.js active +```js src/PortalExample.js active import { useState } from 'react'; import { createPortal } from 'react-dom'; import ModalContent from './ModalContent.js'; @@ -195,7 +195,7 @@ export default function PortalExample() { } ``` -```js ModalContent.js +```js src/ModalContent.js export default function ModalContent({ onClose }) { return (
        @@ -207,7 +207,7 @@ export default function ModalContent({ onClose }) { ``` -```css styles.css +```css src/styles.css .clipping-container { position: relative; border: 1px solid #aaa; @@ -269,7 +269,7 @@ Portals can be useful if your React root is only part of a static or server-rend ``` -```js index.js +```js src/index.js import { StrictMode } from 'react'; import { createRoot } from 'react-dom/client'; import App from './App.js'; @@ -283,7 +283,7 @@ root.render( ); ``` -```js App.js active +```js src/App.js active import { createPortal } from 'react-dom'; const sidebarContentEl = document.getElementById('sidebar-content'); @@ -398,7 +398,7 @@ Here is a complete example you can play with: } ``` -```js App.js +```js src/App.js import { useRef, useEffect, useState } from 'react'; import { createPortal } from 'react-dom'; import { createMapWidget, addPopupToMapWidget } from './map-widget.js'; @@ -428,7 +428,7 @@ export default function Map() { } ``` -```js map-widget.js +```js src/map-widget.js import 'leaflet/dist/leaflet.css'; import * as L from 'leaflet'; diff --git a/src/content/reference/react-dom/findDOMNode.md b/src/content/reference/react-dom/findDOMNode.md index 75c02c73d..8e7b00653 100644 --- a/src/content/reference/react-dom/findDOMNode.md +++ b/src/content/reference/react-dom/findDOMNode.md @@ -80,7 +80,7 @@ Here, the `input` variable will be set to the `` DOM element. This lets y -```js App.js +```js src/App.js import { useState } from 'react'; import AutoselectingInput from './AutoselectingInput.js'; @@ -98,7 +98,7 @@ export default function App() { } ``` -```js AutoselectingInput.js active +```js src/AutoselectingInput.js active import { Component } from 'react'; import { findDOMNode } from 'react-dom'; @@ -128,7 +128,7 @@ Code using `findDOMNode` is fragile because the connection between the JSX node -```js App.js +```js src/App.js import { useState } from 'react'; import AutoselectingInput from './AutoselectingInput.js'; @@ -146,7 +146,7 @@ export default function App() { } ``` -```js AutoselectingInput.js active +```js src/AutoselectingInput.js active import { Component } from 'react'; import { findDOMNode } from 'react-dom'; @@ -171,7 +171,7 @@ In this example, `findDOMNode` is no longer used. Instead, `inputRef = createRef -```js App.js +```js src/App.js import { useState } from 'react'; import AutoselectingInput from './AutoselectingInput.js'; @@ -189,7 +189,7 @@ export default function App() { } ``` -```js AutoselectingInput.js active +```js src/AutoselectingInput.js active import { createRef, Component } from 'react'; class AutoselectingInput extends Component { @@ -216,7 +216,7 @@ In modern React without class components, the equivalent code would call [`useRe -```js App.js +```js src/App.js import { useState } from 'react'; import AutoselectingInput from './AutoselectingInput.js'; @@ -234,7 +234,7 @@ export default function App() { } ``` -```js AutoselectingInput.js active +```js src/AutoselectingInput.js active import { useRef, useEffect } from 'react'; export default function AutoselectingInput() { @@ -261,7 +261,7 @@ In this example, `findDOMNode(this)` finds a DOM node that belongs to another co -```js App.js +```js src/App.js import { useState } from 'react'; import AutoselectingInput from './AutoselectingInput.js'; @@ -279,7 +279,7 @@ export default function App() { } ``` -```js AutoselectingInput.js active +```js src/AutoselectingInput.js active import { Component } from 'react'; import { findDOMNode } from 'react-dom'; import MyInput from './MyInput.js'; @@ -297,7 +297,7 @@ class AutoselectingInput extends Component { export default AutoselectingInput; ``` -```js MyInput.js +```js src/MyInput.js export default function MyInput() { return ; } @@ -316,7 +316,7 @@ This version does that, so it no longer needs `findDOMNode`: -```js App.js +```js src/App.js import { useState } from 'react'; import AutoselectingInput from './AutoselectingInput.js'; @@ -334,7 +334,7 @@ export default function App() { } ``` -```js AutoselectingInput.js active +```js src/AutoselectingInput.js active import { createRef, Component } from 'react'; import MyInput from './MyInput.js'; @@ -356,7 +356,7 @@ class AutoselectingInput extends Component { export default AutoselectingInput; ``` -```js MyInput.js +```js src/MyInput.js import { forwardRef } from 'react'; const MyInput = forwardRef(function MyInput(props, ref) { @@ -372,7 +372,7 @@ Here is how this code would look like with function components instead of classe -```js App.js +```js src/App.js import { useState } from 'react'; import AutoselectingInput from './AutoselectingInput.js'; @@ -390,7 +390,7 @@ export default function App() { } ``` -```js AutoselectingInput.js active +```js src/AutoselectingInput.js active import { useRef, useEffect } from 'react'; import MyInput from './MyInput.js'; @@ -406,7 +406,7 @@ export default function AutoselectingInput() { } ``` -```js MyInput.js +```js src/MyInput.js import { forwardRef } from 'react'; const MyInput = forwardRef(function MyInput(props, ref) { diff --git a/src/content/reference/react-dom/flushSync.md b/src/content/reference/react-dom/flushSync.md index 7b40a7389..a97d194e4 100644 --- a/src/content/reference/react-dom/flushSync.md +++ b/src/content/reference/react-dom/flushSync.md @@ -83,7 +83,7 @@ For example, the browser `onbeforeprint` API allows you to change the page immed -```js App.js active +```js src/App.js active import { useState, useEffect } from 'react'; import { flushSync } from 'react-dom'; diff --git a/src/content/reference/react-dom/hooks/useFormState.md b/src/content/reference/react-dom/hooks/useFormState.md index b2808079c..d68bb55c4 100644 --- a/src/content/reference/react-dom/hooks/useFormState.md +++ b/src/content/reference/react-dom/hooks/useFormState.md @@ -5,7 +5,11 @@ canary: true +<<<<<<< HEAD The `useFormState` Hook is currently only available in React's canary and experimental channels. Learn more about [release channels here](/community/versioning-policy#all-release-channels). In addition, you need to use a framework that supports [React Server Components](/reference/react/use-client) to get the full benefit of `useFormState`. +======= +The `useFormState` Hook is currently only available in React's Canary and experimental channels. Learn more about [release channels here](/community/versioning-policy#all-release-channels). In addition, you need to use a framework that supports [React Server Components](/reference/react/use-client) to get the full benefit of `useFormState`. +>>>>>>> 303ecae3dd4c7b570cf18e0115b94188f6aad5a1 @@ -121,7 +125,11 @@ To display messages such as an error message or toast that's returned by a Serve +<<<<<<< HEAD ```js App.js +======= +```js src/App.js +>>>>>>> 303ecae3dd4c7b570cf18e0115b94188f6aad5a1 import { useState } from "react"; import { useFormState } from "react-dom"; import { addToCart } from "./actions.js"; @@ -148,7 +156,11 @@ export default function App() { } ``` +<<<<<<< HEAD ```js actions.js +======= +```js src/actions.js +>>>>>>> 303ecae3dd4c7b570cf18e0115b94188f6aad5a1 "use server"; export async function addToCart(prevState, queryData) { @@ -161,7 +173,11 @@ export async function addToCart(prevState, queryData) { } ``` +<<<<<<< HEAD ```css styles.css hidden +======= +```css src/styles.css hidden +>>>>>>> 303ecae3dd4c7b570cf18e0115b94188f6aad5a1 form { border: solid 1px black; margin-bottom: 24px; @@ -194,7 +210,11 @@ The return value from a Server Action can be any serializable value. For example +<<<<<<< HEAD ```js App.js +======= +```js src/App.js +>>>>>>> 303ecae3dd4c7b570cf18e0115b94188f6aad5a1 import { useState } from "react"; import { useFormState } from "react-dom"; import { addToCart } from "./actions.js"; @@ -230,7 +250,11 @@ export default function App() { } ``` +<<<<<<< HEAD ```js actions.js +======= +```js src/actions.js +>>>>>>> 303ecae3dd4c7b570cf18e0115b94188f6aad5a1 "use server"; export async function addToCart(prevState, queryData) { @@ -249,7 +273,11 @@ export async function addToCart(prevState, queryData) { } ``` +<<<<<<< HEAD ```css styles.css hidden +======= +```css src/styles.css hidden +>>>>>>> 303ecae3dd4c7b570cf18e0115b94188f6aad5a1 form { border: solid 1px black; margin-bottom: 24px; diff --git a/src/content/reference/react-dom/hooks/useFormStatus.md b/src/content/reference/react-dom/hooks/useFormStatus.md index abaa9b6f2..8733ec0ca 100644 --- a/src/content/reference/react-dom/hooks/useFormStatus.md +++ b/src/content/reference/react-dom/hooks/useFormStatus.md @@ -5,7 +5,7 @@ canary: true -The `useFormStatus` Hook is currently only available in React's canary and experimental channels. Learn more about [React's release channels here](/community/versioning-policy#all-release-channels). +The `useFormStatus` Hook is currently only available in React's Canary and experimental channels. Learn more about [React's release channels here](/community/versioning-policy#all-release-channels). @@ -38,7 +38,7 @@ function Submit() { return } -export default App() { +export default function App() { return ( @@ -86,7 +86,7 @@ Here, we use the `pending` property to indicate the form is submitting. -```js App.js +```js src/App.js import { useFormStatus } from "react-dom"; import { submitForm } from "./actions.js"; @@ -112,7 +112,7 @@ export default function App() { } ``` -```js actions.js hidden +```js src/actions.js hidden export async function submitForm(query) { await new Promise((res) => setTimeout(res, 1000)); } @@ -175,7 +175,7 @@ Here, we have a form where users can request a username. We can use `useFormStat -```js UsernameForm.js active +```js src/UsernameForm.js active import {useState, useMemo, useRef} from 'react'; import {useFormStatus} from 'react-dom'; @@ -216,7 +216,7 @@ export default function UsernameForm() { } ``` -```js App.js +```js src/App.js import UsernameForm from './UsernameForm'; import { submitForm } from "./actions.js"; @@ -229,7 +229,7 @@ export default function App() { } ``` -```js actions.js hidden +```js src/actions.js hidden export async function submitForm(query) { await new Promise((res) => setTimeout(res, 1000)); } diff --git a/src/content/reference/react-dom/hydrate.md b/src/content/reference/react-dom/hydrate.md index 639c7ab25..0d1e1cdf9 100644 --- a/src/content/reference/react-dom/hydrate.md +++ b/src/content/reference/react-dom/hydrate.md @@ -88,7 +88,7 @@ In apps fully built with React, **you will usually only hydrate one "root", once

        Hello, world!

        ``` -```js index.js active +```js src/index.js active import './styles.css'; import { hydrate } from 'react-dom'; import App from './App.js'; @@ -96,7 +96,7 @@ import App from './App.js'; hydrate(, document.getElementById('root')); ``` -```js App.js +```js src/App.js export default function App() { return

        Hello, world!

        ; } @@ -126,7 +126,7 @@ To silence hydration warnings on an element, add `suppressHydrationWarning={true

        Current Date: 01/01/2020

        ``` -```js index.js +```js src/index.js import './styles.css'; import { hydrate } from 'react-dom'; import App from './App.js'; @@ -134,7 +134,7 @@ import App from './App.js'; hydrate(, document.getElementById('root')); ``` -```js App.js active +```js src/App.js active export default function App() { return (

        @@ -164,7 +164,7 @@ If you intentionally need to render something different on the server and the cl

        Is Server

        ``` -```js index.js +```js src/index.js import './styles.css'; import { hydrate } from 'react-dom'; import App from './App.js'; @@ -172,7 +172,7 @@ import App from './App.js'; hydrate(, document.getElementById('root')); ``` -```js App.js active +```js src/App.js active import { useState, useEffect } from "react"; export default function App() { diff --git a/src/content/reference/react-dom/render.md b/src/content/reference/react-dom/render.md index a0f751278..03feb2881 100644 --- a/src/content/reference/react-dom/render.md +++ b/src/content/reference/react-dom/render.md @@ -85,7 +85,7 @@ In apps fully built with React, **you will usually only do this once at startup* -```js index.js active +```js src/index.js active import './styles.css'; import { render } from 'react-dom'; import App from './App.js'; @@ -93,7 +93,7 @@ import App from './App.js'; render(, document.getElementById('root')); ``` -```js App.js +```js src/App.js export default function App() { return

        Hello, world!

        ; } @@ -119,7 +119,7 @@ If your page [isn't fully built with React](/learn/add-react-to-an-existing-proj ``` -```js index.js active +```js src/index.js active import './styles.css'; import { render } from 'react-dom'; import { Comments, Navigation } from './Components.js'; @@ -135,7 +135,7 @@ render( ); ``` -```js Components.js +```js src/Components.js export function Navigation() { return (
          @@ -187,7 +187,7 @@ You can call `render` more than once on the same DOM node. As long as the compon -```js index.js active +```js src/index.js active import { render } from 'react-dom'; import './styles.css'; import App from './App.js'; @@ -202,7 +202,7 @@ setInterval(() => { }, 1000); ``` -```js App.js +```js src/App.js export default function App({counter}) { return ( <> diff --git a/src/content/reference/react-dom/server/renderToNodeStream.md b/src/content/reference/react-dom/server/renderToNodeStream.md index a4ab2e570..fd2464b97 100644 --- a/src/content/reference/react-dom/server/renderToNodeStream.md +++ b/src/content/reference/react-dom/server/renderToNodeStream.md @@ -43,6 +43,9 @@ On the client, call [`hydrateRoot`](/reference/react-dom/client/hydrateRoot) to * `reactNode`: A React node you want to render to HTML. For example, a JSX element like ``. +* **optional** `options`: An object for server render. + * **optional** `identifierPrefix`: A string prefix React uses for IDs generated by [`useId`.](/reference/react/useId) Useful to avoid conflicts when using multiple roots on the same page. Must be the same prefix as passed to [`hydrateRoot`.](/reference/react-dom/client/hydrateRoot#parameters) + #### Returns {/*returns*/} A [Node.js Readable Stream](https://nodejs.org/api/stream.html#readable-streams) that outputs an HTML string. diff --git a/src/content/reference/react-dom/server/renderToStaticMarkup.md b/src/content/reference/react-dom/server/renderToStaticMarkup.md index 01ff17ee6..607affd99 100644 --- a/src/content/reference/react-dom/server/renderToStaticMarkup.md +++ b/src/content/reference/react-dom/server/renderToStaticMarkup.md @@ -35,6 +35,8 @@ It will produce non-interactive HTML output of your React components. #### Parameters {/*parameters*/} * `reactNode`: A React node you want to render to HTML. For example, a JSX node like ``. +* **optional** `options`: An object for server render. + * **optional** `identifierPrefix`: A string prefix React uses for IDs generated by [`useId`.](/reference/react/useId) Useful to avoid conflicts when using multiple roots on the same page. #### Returns {/*returns*/} diff --git a/src/content/reference/react-dom/server/renderToStaticNodeStream.md b/src/content/reference/react-dom/server/renderToStaticNodeStream.md index ec3d58937..47ef74c3c 100644 --- a/src/content/reference/react-dom/server/renderToStaticNodeStream.md +++ b/src/content/reference/react-dom/server/renderToStaticNodeStream.md @@ -37,6 +37,9 @@ The stream will produce non-interactive HTML output of your React components. * `reactNode`: A React node you want to render to HTML. For example, a JSX element like ``. +* **optional** `options`: An object for server render. + * **optional** `identifierPrefix`: A string prefix React uses for IDs generated by [`useId`.](/reference/react/useId) Useful to avoid conflicts when using multiple roots on the same page. + #### Returns {/*returns*/} A [Node.js Readable Stream](https://nodejs.org/api/stream.html#readable-streams) that outputs an HTML string. The resulting HTML can't be hydrated on the client. diff --git a/src/content/reference/react-dom/server/renderToString.md b/src/content/reference/react-dom/server/renderToString.md index 41bc6a982..e12692943 100644 --- a/src/content/reference/react-dom/server/renderToString.md +++ b/src/content/reference/react-dom/server/renderToString.md @@ -42,6 +42,9 @@ On the client, call [`hydrateRoot`](/reference/react-dom/client/hydrateRoot) to * `reactNode`: A React node you want to render to HTML. For example, a JSX node like ``. +* **optional** `options`: An object for server render. + * **optional** `identifierPrefix`: A string prefix React uses for IDs generated by [`useId`.](/reference/react/useId) Useful to avoid conflicts when using multiple roots on the same page. Must be the same prefix as passed to [`hydrateRoot`.](/reference/react-dom/client/hydrateRoot#parameters) + #### Returns {/*returns*/} An HTML string. diff --git a/src/content/reference/react-dom/unmountComponentAtNode.md b/src/content/reference/react-dom/unmountComponentAtNode.md index 12f11dc74..376a9bc2b 100644 --- a/src/content/reference/react-dom/unmountComponentAtNode.md +++ b/src/content/reference/react-dom/unmountComponentAtNode.md @@ -88,7 +88,7 @@ In this example, clicking "Render React App" will render a React app. Click "Unm ``` -```js index.js active +```js src/index.js active import './styles.css'; import { render, unmountComponentAtNode } from 'react-dom'; import App from './App.js'; @@ -104,7 +104,7 @@ document.getElementById('unmount').addEventListener('click', () => { }); ``` -```js App.js +```js src/App.js export default function App() { return

          Hello, world!

          ; } diff --git a/src/content/reference/react/Children.md b/src/content/reference/react/Children.md index 3683cb7cc..81a28c5b3 100644 --- a/src/content/reference/react/Children.md +++ b/src/content/reference/react/Children.md @@ -33,7 +33,7 @@ const mappedChildren = Children.map(children, child => Call `Children.count(children)` to count the number of children in the `children` data structure. -```js RowList.js active +```js src/RowList.js active import { Children } from 'react'; function RowList({ children }) { @@ -66,7 +66,7 @@ The number of nodes inside these `children`. Call `Children.forEach(children, fn, thisArg?)` to run some code for each child in the `children` data structure. -```js RowList.js active +```js src/RowList.js active import { Children } from 'react'; function SeparatorList({ children }) { @@ -100,7 +100,7 @@ function SeparatorList({ children }) { Call `Children.map(children, fn, thisArg?)` to map or transform each child in the `children` data structure. -```js RowList.js active +```js src/RowList.js active import { Children } from 'react'; function RowList({ children }) { @@ -169,7 +169,7 @@ Otherwise, throws an error. Call `Children.toArray(children)` to create an array out of the `children` data structure. -```js ReversedList.js active +```js src/ReversedList.js active import { Children } from 'react'; export default function ReversedList({ children }) { @@ -258,7 +258,7 @@ export default function App() { } ``` -```js RowList.js active +```js src/RowList.js active import { Children } from 'react'; export default function RowList({ children }) { @@ -336,7 +336,7 @@ function MoreRows() { } ``` -```js RowList.js +```js src/RowList.js import { Children } from 'react'; export default function RowList({ children }) { @@ -395,7 +395,7 @@ export default function App() { } ``` -```js SeparatorList.js active +```js src/SeparatorList.js active import { Children } from 'react'; export default function SeparatorList({ children }) { @@ -439,7 +439,7 @@ export default function App() { } ``` -```js RowList.js active +```js src/RowList.js active import { Children } from 'react'; export default function RowList({ children }) { @@ -510,7 +510,7 @@ export default function App() { } ``` -```js ReversedList.js active +```js src/ReversedList.js active import { Children } from 'react'; export default function ReversedList({ children }) { @@ -572,7 +572,7 @@ export default function App() { } ``` -```js RowList.js +```js src/RowList.js export function RowList({ children }) { return (
          @@ -639,7 +639,7 @@ function MoreRows() { } ``` -```js RowList.js +```js src/RowList.js export function RowList({ children }) { return (
          @@ -698,7 +698,7 @@ export default function App() { } ``` -```js RowList.js +```js src/RowList.js export function RowList({ rows }) { return (
          @@ -761,7 +761,7 @@ export default function App() { } ``` -```js TabSwitcher.js +```js src/TabSwitcher.js import { useState } from 'react'; export default function TabSwitcher({ tabs }) { @@ -817,7 +817,7 @@ export default function App() { } ``` -```js TabSwitcher.js +```js src/TabSwitcher.js import { useState } from 'react'; export default function TabSwitcher({ tabIds, getHeader, renderContent }) { @@ -869,7 +869,7 @@ export default function App() { } ``` -```js RowList.js +```js src/RowList.js import { Fragment } from 'react'; export function RowList({ rowIds, renderRow }) { diff --git a/src/content/reference/react/Component.md b/src/content/reference/react/Component.md index f8884608b..46406ff5e 100644 --- a/src/content/reference/react/Component.md +++ b/src/content/reference/react/Component.md @@ -1221,7 +1221,7 @@ For example, this `ChatRoom` component keeps a chat connection synchronized with -```js App.js +```js src/App.js import { useState } from 'react'; import ChatRoom from './ChatRoom.js'; @@ -1251,7 +1251,7 @@ export default function App() { } ``` -```js ChatRoom.js active +```js src/ChatRoom.js active import { Component } from 'react'; import { createConnection } from './chat.js'; @@ -1312,7 +1312,7 @@ export default class ChatRoom extends Component { } ``` -```js chat.js +```js src/chat.js export function createConnection(serverUrl, roomId) { // A real implementation would actually connect to the server return { @@ -1601,7 +1601,7 @@ Suppose you're converting this `ChatRoom` class component with lifecycle methods -```js App.js +```js src/App.js import { useState } from 'react'; import ChatRoom from './ChatRoom.js'; @@ -1631,7 +1631,7 @@ export default function App() { } ``` -```js ChatRoom.js active +```js src/ChatRoom.js active import { Component } from 'react'; import { createConnection } from './chat.js'; @@ -1692,7 +1692,7 @@ export default class ChatRoom extends Component { } ``` -```js chat.js +```js src/chat.js export function createConnection(serverUrl, roomId) { // A real implementation would actually connect to the server return { @@ -1741,7 +1741,7 @@ This [`useEffect`](/reference/react/useEffect) call is equivalent to the logic i -```js App.js +```js src/App.js import { useState } from 'react'; import ChatRoom from './ChatRoom.js'; @@ -1771,7 +1771,7 @@ export default function App() { } ``` -```js ChatRoom.js active +```js src/ChatRoom.js active import { useState, useEffect } from 'react'; import { createConnection } from './chat.js'; @@ -1801,7 +1801,7 @@ export default function ChatRoom({ roomId }) { } ``` -```js chat.js +```js src/chat.js export function createConnection(serverUrl, roomId) { // A real implementation would actually connect to the server return { diff --git a/src/content/reference/react/StrictMode.md b/src/content/reference/react/StrictMode.md index b7ca2227c..0b64c5ed9 100644 --- a/src/content/reference/react/StrictMode.md +++ b/src/content/reference/react/StrictMode.md @@ -95,7 +95,7 @@ Strict Mode enables the following checks in development: --- -### Enabling strict mode for a part of the app {/*enabling-strict-mode-for-a-part-of-the-app*/} +### Enabling Strict Mode for a part of the app {/*enabling-strict-mode-for-a-part-of-the-app*/} You can also enable Strict Mode for any part of your application: @@ -140,7 +140,7 @@ This `StoryTray` component takes an array of `stories` and adds one last "Create -```js index.js +```js src/index.js import { createRoot } from 'react-dom/client'; import './styles.css'; @@ -150,7 +150,7 @@ const root = createRoot(document.getElementById("root")); root.render(); ``` -```js App.js +```js src/App.js import { useState } from 'react'; import StoryTray from './StoryTray.js'; @@ -175,7 +175,7 @@ export default function App() { } ``` -```js StoryTray.js active +```js src/StoryTray.js active export default function StoryTray({ stories }) { const items = stories; items.push({ id: 'create', label: 'Create Story' }); @@ -218,7 +218,7 @@ This mistake will become more noticeable if the `StoryTray` component re-renders -```js index.js +```js src/index.js import { createRoot } from 'react-dom/client'; import './styles.css'; @@ -228,7 +228,7 @@ const root = createRoot(document.getElementById('root')); root.render(); ``` -```js App.js +```js src/App.js import { useState } from 'react'; import StoryTray from './StoryTray.js'; @@ -253,7 +253,7 @@ export default function App() { } ``` -```js StoryTray.js active +```js src/StoryTray.js active import { useState } from 'react'; export default function StoryTray({ stories }) { @@ -316,7 +316,7 @@ This would [make the `StoryTray` function pure.](/learn/keeping-components-pure) -```js index.js +```js src/index.js import { StrictMode } from 'react'; import { createRoot } from 'react-dom/client'; import './styles.css'; @@ -331,7 +331,7 @@ root.render( ); ``` -```js App.js +```js src/App.js import { useState } from 'react'; import StoryTray from './StoryTray.js'; @@ -356,7 +356,7 @@ export default function App() { } ``` -```js StoryTray.js active +```js src/StoryTray.js active export default function StoryTray({ stories }) { const items = stories; items.push({ id: 'create', label: 'Create Story' }); @@ -397,7 +397,7 @@ li { -```js index.js +```js src/index.js import { StrictMode } from 'react'; import { createRoot } from 'react-dom/client'; import './styles.css'; @@ -412,7 +412,7 @@ root.render( ); ``` -```js App.js +```js src/App.js import { useState } from 'react'; import StoryTray from './StoryTray.js'; @@ -437,7 +437,7 @@ export default function App() { } ``` -```js StoryTray.js active +```js src/StoryTray.js active import { useState } from 'react'; export default function StoryTray({ stories }) { @@ -509,7 +509,7 @@ Consider this example that connects a component to a chat: -```js index.js +```js src/index.js import { createRoot } from 'react-dom/client'; import './styles.css'; @@ -535,7 +535,7 @@ export default function ChatRoom() { } ``` -```js chat.js +```js src/chat.js let connections = 0; export function createConnection(serverUrl, roomId) { @@ -568,7 +568,7 @@ To make the issue more obvious, let's implement a feature. In the example below, -```js index.js +```js src/index.js import { createRoot } from 'react-dom/client'; import './styles.css'; @@ -619,7 +619,7 @@ export default function App() { } ``` -```js chat.js +```js src/chat.js let connections = 0; export function createConnection(serverUrl, roomId) { @@ -662,7 +662,7 @@ Now that your Effect "cleans up" after itself and destroys the outdated connecti -```js index.js +```js src/index.js import { StrictMode } from 'react'; import { createRoot } from 'react-dom/client'; import './styles.css'; @@ -693,7 +693,7 @@ export default function ChatRoom() { } ``` -```js chat.js +```js src/chat.js let connections = 0; export function createConnection(serverUrl, roomId) { @@ -726,7 +726,7 @@ Strict Mode lets you notice such mistakes early in the process. When you fix you -```js index.js +```js src/index.js import { StrictMode } from 'react'; import { createRoot } from 'react-dom/client'; import './styles.css'; @@ -783,7 +783,7 @@ export default function App() { } ``` -```js chat.js +```js src/chat.js let connections = 0; export function createConnection(serverUrl, roomId) { diff --git a/src/content/reference/react/Suspense.md b/src/content/reference/react/Suspense.md index d94003783..4ec3dd7aa 100644 --- a/src/content/reference/react/Suspense.md +++ b/src/content/reference/react/Suspense.md @@ -69,7 +69,7 @@ In the example below, the `Albums` component *suspends* while fetching the list } ``` -```js App.js hidden +```js src/App.js hidden import { useState } from 'react'; import ArtistPage from './ArtistPage.js'; @@ -94,7 +94,7 @@ export default function App() { } ``` -```js ArtistPage.js active +```js src/ArtistPage.js active import { Suspense } from 'react'; import Albums from './Albums.js'; @@ -114,7 +114,7 @@ function Loading() { } ``` -```js Albums.js hidden +```js src/Albums.js hidden import { fetchData } from './data.js'; // Note: this component is written using an experimental API @@ -162,7 +162,7 @@ function use(promise) { } ``` -```js data.js hidden +```js src/data.js hidden // Note: the way you would do data fetching depends on // the framework that you use together with Suspense. // Normally, the caching logic would be inside a framework. @@ -300,7 +300,7 @@ In the example below, both `Biography` and `Albums` fetch some data. However, be } ``` -```js App.js hidden +```js src/App.js hidden import { useState } from 'react'; import ArtistPage from './ArtistPage.js'; @@ -325,7 +325,7 @@ export default function App() { } ``` -```js ArtistPage.js active +```js src/ArtistPage.js active import { Suspense } from 'react'; import Albums from './Albums.js'; import Biography from './Biography.js'; @@ -350,7 +350,7 @@ function Loading() { } ``` -```js Panel.js +```js src/Panel.js export default function Panel({ children }) { return (
          @@ -360,7 +360,7 @@ export default function Panel({ children }) { } ``` -```js Biography.js hidden +```js src/Biography.js hidden import { fetchData } from './data.js'; // Note: this component is written using an experimental API @@ -404,7 +404,7 @@ function use(promise) { } ``` -```js Albums.js hidden +```js src/Albums.js hidden import { fetchData } from './data.js'; // Note: this component is written using an experimental API @@ -452,7 +452,7 @@ function use(promise) { } ``` -```js data.js hidden +```js src/data.js hidden // Note: the way you would do data fetching depends on // the framework that you use together with Suspense. // Normally, the caching logic would be inside a framework. @@ -625,7 +625,7 @@ The sequence will be: } ``` -```js App.js hidden +```js src/App.js hidden import { useState } from 'react'; import ArtistPage from './ArtistPage.js'; @@ -650,7 +650,7 @@ export default function App() { } ``` -```js ArtistPage.js active +```js src/ArtistPage.js active import { Suspense } from 'react'; import Albums from './Albums.js'; import Biography from './Biography.js'; @@ -687,7 +687,7 @@ function AlbumsGlimmer() { } ``` -```js Panel.js +```js src/Panel.js export default function Panel({ children }) { return (
          @@ -697,7 +697,7 @@ export default function Panel({ children }) { } ``` -```js Biography.js hidden +```js src/Biography.js hidden import { fetchData } from './data.js'; // Note: this component is written using an experimental API @@ -741,7 +741,7 @@ function use(promise) { } ``` -```js Albums.js hidden +```js src/Albums.js hidden import { fetchData } from './data.js'; // Note: this component is written using an experimental API @@ -789,7 +789,7 @@ function use(promise) { } ``` -```js data.js hidden +```js src/data.js hidden // Note: the way you would do data fetching depends on // the framework that you use together with Suspense. // Normally, the caching logic would be inside a framework. @@ -944,7 +944,7 @@ In this example, the `SearchResults` component suspends while fetching the searc } ``` -```js App.js +```js src/App.js import { Suspense, useState } from 'react'; import SearchResults from './SearchResults.js'; @@ -964,7 +964,7 @@ export default function App() { } ``` -```js SearchResults.js hidden +```js src/SearchResults.js hidden import { fetchData } from './data.js'; // Note: this component is written using an experimental API @@ -1018,7 +1018,7 @@ function use(promise) { } ``` -```js data.js hidden +```js src/data.js hidden // Note: the way you would do data fetching depends on // the framework that you use together with Suspense. // Normally, the caching logic would be inside a framework. @@ -1169,7 +1169,7 @@ Enter `"a"` in the example below, wait for the results to load, and then edit th } ``` -```js App.js +```js src/App.js import { Suspense, useState, useDeferredValue } from 'react'; import SearchResults from './SearchResults.js'; @@ -1193,7 +1193,7 @@ export default function App() { } ``` -```js SearchResults.js hidden +```js src/SearchResults.js hidden import { fetchData } from './data.js'; // Note: this component is written using an experimental API @@ -1247,7 +1247,7 @@ function use(promise) { } ``` -```js data.js hidden +```js src/data.js hidden // Note: the way you would do data fetching depends on // the framework that you use together with Suspense. // Normally, the caching logic would be inside a framework. @@ -1375,7 +1375,7 @@ When a component suspends, the closest parent Suspense boundary switches to show } ``` -```js App.js +```js src/App.js import { Suspense, useState } from 'react'; import IndexPage from './IndexPage.js'; import ArtistPage from './ArtistPage.js'; @@ -1423,7 +1423,7 @@ function BigSpinner() { } ``` -```js Layout.js +```js src/Layout.js export default function Layout({ children }) { return (
          @@ -1438,7 +1438,7 @@ export default function Layout({ children }) { } ``` -```js IndexPage.js +```js src/IndexPage.js export default function IndexPage({ navigate }) { return ( +======= +export default function App() { + return ( +
          + + +
          + ); +>>>>>>> 303ecae3dd4c7b570cf18e0115b94188f6aad5a1 } ``` diff --git a/src/content/reference/react/use.md b/src/content/reference/react/use.md index b726e67db..1cf73b7b1 100644 --- a/src/content/reference/react/use.md +++ b/src/content/reference/react/use.md @@ -5,7 +5,7 @@ canary: true -The `use` Hook is currently only available in React's canary and experimental channels. Learn more about [React's release channels here](/community/versioning-policy#all-release-channels). +The `use` Hook is currently only available in React's Canary and experimental channels. Learn more about [React's release channels here](/community/versioning-policy#all-release-channels). @@ -247,7 +247,7 @@ Because `Message` is wrapped in -```js message.js active +```js src/message.js active "use client"; import { use, Suspense } from "react"; @@ -266,7 +266,7 @@ export function MessageContainer({ messagePromise }) { } ``` -```js App.js hidden +```js src/App.js hidden import { useState } from "react"; import { MessageContainer } from "./message.js"; @@ -290,7 +290,7 @@ export default function App() { } ``` -```js index.js hidden +```js src/index.js hidden // TODO: update to import from stable // react instead of canary once the `use` // Hook is in a stable release of React @@ -364,7 +364,7 @@ If you'd like to display an error to your users when a Promise is rejected, you -```js message.js active +```js src/message.js active "use client"; import { use, Suspense } from "react"; @@ -386,7 +386,7 @@ function Message({ messagePromise }) { } ``` -```js App.js hidden +```js src/App.js hidden import { useState } from "react"; import { MessageContainer } from "./message.js"; @@ -410,7 +410,7 @@ export default function App() { } ``` -```js index.js hidden +```js src/index.js hidden // TODO: update to import from stable // react instead of canary once the `use` // Hook is in a stable release of React diff --git a/src/content/reference/react/useCallback.md b/src/content/reference/react/useCallback.md index 63b36a600..93ce700e4 100644 --- a/src/content/reference/react/useCallback.md +++ b/src/content/reference/react/useCallback.md @@ -251,7 +251,7 @@ Next, try toggling the theme. **Thanks to `useCallback` together with [`memo`](/ -```js App.js +```js src/App.js import { useState } from 'react'; import ProductPage from './ProductPage.js'; @@ -278,7 +278,7 @@ export default function App() { } ``` -```js ProductPage.js active +```js src/ProductPage.js active import { useCallback } from 'react'; import ShippingForm from './ShippingForm.js'; @@ -304,7 +304,7 @@ function post(url, data) { } ``` -```js ShippingForm.js +```js src/ShippingForm.js import { memo, useState } from 'react'; const ShippingForm = memo(function ShippingForm({ onSubmit }) { @@ -391,7 +391,7 @@ Unlike in the previous example, toggling the theme is also slow now! This is bec -```js App.js +```js src/App.js import { useState } from 'react'; import ProductPage from './ProductPage.js'; @@ -418,7 +418,7 @@ export default function App() { } ``` -```js ProductPage.js active +```js src/ProductPage.js active import ShippingForm from './ShippingForm.js'; export default function ProductPage({ productId, referrer, theme }) { @@ -443,7 +443,7 @@ function post(url, data) { } ``` -```js ShippingForm.js +```js src/ShippingForm.js import { memo, useState } from 'react'; const ShippingForm = memo(function ShippingForm({ onSubmit }) { @@ -525,7 +525,7 @@ However, here is the same code **with the artificial slowdown removed.** Does th -```js App.js +```js src/App.js import { useState } from 'react'; import ProductPage from './ProductPage.js'; @@ -552,7 +552,7 @@ export default function App() { } ``` -```js ProductPage.js active +```js src/ProductPage.js active import ShippingForm from './ShippingForm.js'; export default function ProductPage({ productId, referrer, theme }) { @@ -577,7 +577,7 @@ function post(url, data) { } ``` -```js ShippingForm.js +```js src/ShippingForm.js import { memo, useState } from 'react'; const ShippingForm = memo(function ShippingForm({ onSubmit }) { diff --git a/src/content/reference/react/useContext.md b/src/content/reference/react/useContext.md index ed231c394..bba445d0d 100644 --- a/src/content/reference/react/useContext.md +++ b/src/content/reference/react/useContext.md @@ -745,7 +745,7 @@ Read a [full walkthrough](/learn/scaling-up-with-reducer-and-context) of this ex -```js App.js +```js src/App.js import AddTask from './AddTask.js'; import TaskList from './TaskList.js'; import { TasksProvider } from './TasksContext.js'; @@ -761,7 +761,7 @@ export default function TaskApp() { } ``` -```js TasksContext.js +```js src/TasksContext.js import { createContext, useContext, useReducer } from 'react'; const TasksContext = createContext(null); @@ -825,7 +825,7 @@ const initialTasks = [ ]; ``` -```js AddTask.js +```js src/AddTask.js import { useState, useContext } from 'react'; import { useTasksDispatch } from './TasksContext.js'; @@ -854,7 +854,7 @@ export default function AddTask() { let nextId = 3; ``` -```js TaskList.js +```js src/TaskList.js import { useState, useContext } from 'react'; import { useTasks, useTasksDispatch } from './TasksContext.js'; @@ -1222,7 +1222,7 @@ export default function Page() { } ``` -```js Section.js +```js src/Section.js import { useContext } from 'react'; import { LevelContext } from './LevelContext.js'; @@ -1238,7 +1238,7 @@ export default function Section({ children }) { } ``` -```js Heading.js +```js src/Heading.js import { useContext } from 'react'; import { LevelContext } from './LevelContext.js'; @@ -1265,7 +1265,7 @@ export default function Heading({ children }) { } ``` -```js LevelContext.js +```js src/LevelContext.js import { createContext } from 'react'; export const LevelContext = createContext(0); diff --git a/src/content/reference/react/useDebugValue.md b/src/content/reference/react/useDebugValue.md index 8826665e7..62db9e6b2 100644 --- a/src/content/reference/react/useDebugValue.md +++ b/src/content/reference/react/useDebugValue.md @@ -80,7 +80,7 @@ export default function App() { } ``` -```js useOnlineStatus.js active +```js src/useOnlineStatus.js active import { useSyncExternalStore, useDebugValue } from 'react'; export function useOnlineStatus() { diff --git a/src/content/reference/react/useDeferredValue.md b/src/content/reference/react/useDeferredValue.md index 74fdab8ae..dcd8f98d0 100644 --- a/src/content/reference/react/useDeferredValue.md +++ b/src/content/reference/react/useDeferredValue.md @@ -112,7 +112,7 @@ In this example, the `SearchResults` component [suspends](/reference/react/Suspe } ``` -```js App.js +```js src/App.js import { Suspense, useState } from 'react'; import SearchResults from './SearchResults.js'; @@ -132,7 +132,7 @@ export default function App() { } ``` -```js SearchResults.js hidden +```js src/SearchResults.js hidden import { fetchData } from './data.js'; // Note: this component is written using an experimental API @@ -186,7 +186,7 @@ function use(promise) { } ``` -```js data.js hidden +```js src/data.js hidden // Note: the way you would do data fetching depends on // the framework that you use together with Suspense. // Normally, the caching logic would be inside a framework. @@ -326,7 +326,7 @@ Enter `"a"` in the example below, wait for the results to load, and then edit th } ``` -```js App.js +```js src/App.js import { Suspense, useState, useDeferredValue } from 'react'; import SearchResults from './SearchResults.js'; @@ -347,7 +347,7 @@ export default function App() { } ``` -```js SearchResults.js hidden +```js src/SearchResults.js hidden import { fetchData } from './data.js'; // Note: this component is written using an experimental API @@ -401,7 +401,7 @@ function use(promise) { } ``` -```js data.js hidden +```js src/data.js hidden // Note: the way you would do data fetching depends on // the framework that you use together with Suspense. // Normally, the caching logic would be inside a framework. @@ -549,7 +549,7 @@ With this change, as soon as you start typing, the stale result list gets slight } ``` -```js App.js +```js src/App.js import { Suspense, useState, useDeferredValue } from 'react'; import SearchResults from './SearchResults.js'; @@ -576,7 +576,7 @@ export default function App() { } ``` -```js SearchResults.js hidden +```js src/SearchResults.js hidden import { fetchData } from './data.js'; // Note: this component is written using an experimental API @@ -630,7 +630,7 @@ function use(promise) { } ``` -```js data.js hidden +```js src/data.js hidden // Note: the way you would do data fetching depends on // the framework that you use together with Suspense. // Normally, the caching logic would be inside a framework. @@ -800,7 +800,7 @@ export default function App() { } ``` -```js SlowList.js +```js src/SlowList.js import { memo } from 'react'; const SlowList = memo(function SlowList({ text }) { @@ -877,7 +877,7 @@ export default function App() { } ``` -```js SlowList.js +```js src/SlowList.js import { memo } from 'react'; const SlowList = memo(function SlowList({ text }) { diff --git a/src/content/reference/react/useEffect.md b/src/content/reference/react/useEffect.md index e6e4da103..d7659c5e9 100644 --- a/src/content/reference/react/useEffect.md +++ b/src/content/reference/react/useEffect.md @@ -193,7 +193,7 @@ export default function App() { } ``` -```js chat.js +```js src/chat.js export function createConnection(serverUrl, roomId) { // A real implementation would actually connect to the server return { @@ -317,7 +317,7 @@ export default function App() { } ``` -```js animation.js +```js src/animation.js export class FadeInAnimation { constructor(node) { this.node = node; @@ -393,7 +393,7 @@ export default function App() { } ``` -```js ModalDialog.js active +```js src/ModalDialog.js active import { useEffect, useRef } from 'react'; export default function ModalDialog({ isOpen, children }) { @@ -454,7 +454,7 @@ function LongSection() { } ``` -```js Box.js active +```js src/Box.js active import { useRef, useEffect } from 'react'; export default function Box() { @@ -597,7 +597,7 @@ export default function App() { } ``` -```js useChatRoom.js +```js src/useChatRoom.js import { useEffect } from 'react'; import { createConnection } from './chat.js'; @@ -612,7 +612,7 @@ export function useChatRoom({ serverUrl, roomId }) { } ``` -```js chat.js +```js src/chat.js export function createConnection(serverUrl, roomId) { // A real implementation would actually connect to the server return { @@ -669,7 +669,7 @@ export default function App() { } ``` -```js useWindowListener.js +```js src/useWindowListener.js import { useState, useEffect } from 'react'; export function useWindowListener(eventType, listener) { @@ -722,7 +722,7 @@ function LongSection() { } ``` -```js Box.js active +```js src/Box.js active import { useRef, useEffect } from 'react'; import { useIntersectionObserver } from './useIntersectionObserver.js'; @@ -752,7 +752,7 @@ export default function Box() { } ``` -```js useIntersectionObserver.js +```js src/useIntersectionObserver.js import { useState, useEffect } from 'react'; export function useIntersectionObserver(ref) { @@ -810,7 +810,7 @@ For example, if you have a third-party map widget or a video player component wr } ``` -```js App.js +```js src/App.js import { useState } from 'react'; import Map from './Map.js'; @@ -828,7 +828,7 @@ export default function App() { } ``` -```js Map.js active +```js src/Map.js active import { useRef, useEffect } from 'react'; import { MapWidget } from './map-widget.js'; @@ -854,7 +854,7 @@ export default function Map({ zoomLevel }) { } ``` -```js map-widget.js +```js src/map-widget.js import 'leaflet/dist/leaflet.css'; import * as L from 'leaflet'; @@ -926,7 +926,7 @@ Note the `ignore` variable which is initialized to `false`, and is set to `true` -```js App.js +```js src/App.js import { useState, useEffect } from 'react'; import { fetchBio } from './api.js'; @@ -962,7 +962,7 @@ export default function Page() { } ``` -```js api.js hidden +```js src/api.js hidden export async function fetchBio(person) { const delay = person === 'Bob' ? 2000 : 200; return new Promise(resolve => { @@ -979,7 +979,7 @@ You can also rewrite using the [`async` / `await`](https://developer.mozilla.org -```js App.js +```js src/App.js import { useState, useEffect } from 'react'; import { fetchBio } from './api.js'; @@ -1018,7 +1018,7 @@ export default function Page() { } ``` -```js api.js hidden +```js src/api.js hidden export async function fetchBio(person) { const delay = person === 'Bob' ? 2000 : 200; return new Promise(resolve => { @@ -1214,7 +1214,7 @@ export default function App() { } ``` -```js chat.js +```js src/chat.js export function createConnection(serverUrl, roomId) { // A real implementation would actually connect to the server return { @@ -1295,7 +1295,7 @@ export default function App() { } ``` -```js chat.js +```js src/chat.js export function createConnection(serverUrl, roomId) { // A real implementation would actually connect to the server return { @@ -1388,7 +1388,7 @@ export default function App() { } ``` -```js chat.js +```js src/chat.js export function createConnection(serverUrl, roomId) { // A real implementation would actually connect to the server return { @@ -1551,7 +1551,7 @@ export default function App() { } ``` -```js chat.js +```js src/chat.js export function createConnection({ serverUrl, roomId }) { // A real implementation would actually connect to the server return { @@ -1661,7 +1661,7 @@ export default function App() { } ``` -```js chat.js +```js src/chat.js export function createConnection({ serverUrl, roomId }) { // A real implementation would actually connect to the server return { diff --git a/src/content/reference/react/useId.md b/src/content/reference/react/useId.md index 96a5e25a2..a9b37b292 100644 --- a/src/content/reference/react/useId.md +++ b/src/content/reference/react/useId.md @@ -269,7 +269,7 @@ export default function App() { } ``` -```js index.js active +```js src/index.js active import { createRoot } from 'react-dom/client'; import App from './App.js'; import './styles.css'; @@ -302,3 +302,36 @@ input { margin: 5px; } ``` +<<<<<<< HEAD +======= + +--- + +### Using the same ID prefix on the client and the server {/*using-the-same-id-prefix-on-the-client-and-the-server*/} + +If you [render multiple independent React apps on the same page](#specifying-a-shared-prefix-for-all-generated-ids), and some of these apps are server-rendered, make sure that the `identifierPrefix` you pass to the [`hydrateRoot`](/reference/react-dom/client/hydrateRoot) call on the client side is the same as the `identifierPrefix` you pass to the [server APIs](/reference/react-dom/server) such as [`renderToPipeableStream`.](/reference/react-dom/server/renderToPipeableStream) + +```js +// Server +import { renderToPipeableStream } from 'react-dom/server'; + +const { pipe } = renderToPipeableStream( + , + { identifierPrefix: 'react-app1' } +); +``` + +```js +// Client +import { hydrateRoot } from 'react-dom/client'; + +const domNode = document.getElementById('root'); +const root = hydrateRoot( + domNode, + reactNode, + { identifierPrefix: 'react-app1' } +); +``` + +You do not need to pass `identifierPrefix` if you only have one React app on the page. +>>>>>>> 303ecae3dd4c7b570cf18e0115b94188f6aad5a1 diff --git a/src/content/reference/react/useImperativeHandle.md b/src/content/reference/react/useImperativeHandle.md index 12ab715ef..abd93cd4c 100644 --- a/src/content/reference/react/useImperativeHandle.md +++ b/src/content/reference/react/useImperativeHandle.md @@ -133,7 +133,7 @@ export default function Form() { } ``` -```js MyInput.js +```js src/MyInput.js import { forwardRef, useRef, useImperativeHandle } from 'react'; const MyInput = forwardRef(function MyInput(props, ref) { @@ -194,7 +194,7 @@ export default function Page() { } ``` -```js Post.js +```js src/Post.js import { forwardRef, useRef, useImperativeHandle } from 'react'; import CommentList from './CommentList.js'; import AddComment from './AddComment.js'; @@ -227,7 +227,7 @@ export default Post; ``` -```js CommentList.js +```js src/CommentList.js import { forwardRef, useRef, useImperativeHandle } from 'react'; const CommentList = forwardRef(function CommentList(props, ref) { @@ -257,7 +257,7 @@ const CommentList = forwardRef(function CommentList(props, ref) { export default CommentList; ``` -```js AddComment.js +```js src/AddComment.js import { forwardRef, useRef, useImperativeHandle } from 'react'; const AddComment = forwardRef(function AddComment(props, ref) { diff --git a/src/content/reference/react/useLayoutEffect.md b/src/content/reference/react/useLayoutEffect.md index 1b65ce3b5..0d7b04841 100644 --- a/src/content/reference/react/useLayoutEffect.md +++ b/src/content/reference/react/useLayoutEffect.md @@ -149,7 +149,7 @@ export default function App() { } ``` -```js ButtonWithTooltip.js +```js src/ButtonWithTooltip.js import { useState, useRef } from 'react'; import Tooltip from './Tooltip.js'; @@ -185,7 +185,7 @@ export default function ButtonWithTooltip({ tooltipContent, ...rest }) { } ``` -```js Tooltip.js active +```js src/Tooltip.js active import { useRef, useLayoutEffect, useState } from 'react'; import { createPortal } from 'react-dom'; import TooltipContainer from './TooltipContainer.js'; @@ -220,7 +220,7 @@ export default function Tooltip({ children, targetRect }) { } ``` -```js TooltipContainer.js +```js src/TooltipContainer.js export default function TooltipContainer({ children, x, y, contentRef }) { return (
          -```js App.js +```js src/App.js import { useState } from 'react'; import { createTodos } from './utils.js'; import TodoList from './TodoList.js'; @@ -219,7 +219,7 @@ export default function App() { ``` -```js TodoList.js active +```js src/TodoList.js active import { useMemo } from 'react'; import { filterTodos } from './utils.js' @@ -246,7 +246,7 @@ export default function TodoList({ todos, theme, tab }) { } ``` -```js utils.js +```js src/utils.js export function createTodos() { const todos = []; for (let i = 0; i < 50; i++) { @@ -307,7 +307,7 @@ Unlike in the previous example, toggling the theme is also slow now! This is bec -```js App.js +```js src/App.js import { useState } from 'react'; import { createTodos } from './utils.js'; import TodoList from './TodoList.js'; @@ -349,7 +349,7 @@ export default function App() { ``` -```js TodoList.js active +```js src/TodoList.js active import { filterTodos } from './utils.js' export default function TodoList({ todos, theme, tab }) { @@ -372,7 +372,7 @@ export default function TodoList({ todos, theme, tab }) { } ``` -```js utils.js +```js src/utils.js export function createTodos() { const todos = []; for (let i = 0; i < 50; i++) { @@ -427,7 +427,7 @@ However, here is the same code **with the artificial slowdown removed.** Does th -```js App.js +```js src/App.js import { useState } from 'react'; import { createTodos } from './utils.js'; import TodoList from './TodoList.js'; @@ -469,7 +469,7 @@ export default function App() { ``` -```js TodoList.js active +```js src/TodoList.js active import { filterTodos } from './utils.js' export default function TodoList({ todos, theme, tab }) { @@ -491,7 +491,7 @@ export default function TodoList({ todos, theme, tab }) { } ``` -```js utils.js +```js src/utils.js export function createTodos() { const todos = []; for (let i = 0; i < 50; i++) { @@ -651,7 +651,7 @@ Next, try toggling the theme. **Thanks to `useMemo` together with [`memo`](/refe -```js App.js +```js src/App.js import { useState } from 'react'; import { createTodos } from './utils.js'; import TodoList from './TodoList.js'; @@ -692,7 +692,7 @@ export default function App() { } ``` -```js TodoList.js active +```js src/TodoList.js active import { useMemo } from 'react'; import List from './List.js'; import { filterTodos } from './utils.js' @@ -711,7 +711,7 @@ export default function TodoList({ todos, theme, tab }) { } ``` -```js List.js +```js src/List.js import { memo } from 'react'; const List = memo(function List({ items }) { @@ -738,7 +738,7 @@ const List = memo(function List({ items }) { export default List; ``` -```js utils.js +```js src/utils.js export function createTodos() { const todos = []; for (let i = 0; i < 50; i++) { @@ -793,7 +793,7 @@ Unlike in the previous example, toggling the theme is also slow now! This is bec -```js App.js +```js src/App.js import { useState } from 'react'; import { createTodos } from './utils.js'; import TodoList from './TodoList.js'; @@ -834,7 +834,7 @@ export default function App() { } ``` -```js TodoList.js active +```js src/TodoList.js active import List from './List.js'; import { filterTodos } from './utils.js' @@ -849,7 +849,7 @@ export default function TodoList({ todos, theme, tab }) { } ``` -```js List.js +```js src/List.js import { memo } from 'react'; const List = memo(function List({ items }) { @@ -876,7 +876,7 @@ const List = memo(function List({ items }) { export default List; ``` -```js utils.js +```js src/utils.js export function createTodos() { const todos = []; for (let i = 0; i < 50; i++) { @@ -925,7 +925,7 @@ However, here is the same code **with the artificial slowdown removed.** Does th -```js App.js +```js src/App.js import { useState } from 'react'; import { createTodos } from './utils.js'; import TodoList from './TodoList.js'; @@ -966,7 +966,7 @@ export default function App() { } ``` -```js TodoList.js active +```js src/TodoList.js active import List from './List.js'; import { filterTodos } from './utils.js' @@ -980,7 +980,7 @@ export default function TodoList({ todos, theme, tab }) { } ``` -```js List.js +```js src/List.js import { memo } from 'react'; function List({ items }) { @@ -1001,7 +1001,7 @@ function List({ items }) { export default memo(List); ``` -```js utils.js +```js src/utils.js export function createTodos() { const todos = []; for (let i = 0; i < 50; i++) { diff --git a/src/content/reference/react/useOptimistic.md b/src/content/reference/react/useOptimistic.md index 47593a0ae..6b0c475df 100644 --- a/src/content/reference/react/useOptimistic.md +++ b/src/content/reference/react/useOptimistic.md @@ -5,7 +5,11 @@ canary: true +<<<<<<< HEAD The `useOptimistic` Hook is currently only available in React's canary and experimental channels. Learn more about [React's release channels here](/community/versioning-policy#all-release-channels). +======= +The `useOptimistic` Hook is currently only available in React's Canary and experimental channels. Learn more about [React's release channels here](/community/versioning-policy#all-release-channels). +>>>>>>> 303ecae3dd4c7b570cf18e0115b94188f6aad5a1 @@ -27,7 +31,11 @@ The `useOptimistic` Hook is currently only available in React's canary and exper ### `useOptimistic(state, updateFn)` {/*use*/} +<<<<<<< HEAD `useOptimistic` is a React hook that lets you show a different state while an async action is underway. It accepts some state as an argument and returns a copy of that state that can be different during the duration of an async action such as a network request. You provide a function that takes the current state and the input to the action, and returns the optimistic state to be used while the action is pending. +======= +`useOptimistic` is a React Hook that lets you show a different state while an async action is underway. It accepts some state as an argument and returns a copy of that state that can be different during the duration of an async action such as a network request. You provide a function that takes the current state and the input to the action, and returns the optimistic state to be used while the action is pending. +>>>>>>> 303ecae3dd4c7b570cf18e0115b94188f6aad5a1 This state is called the "optimistic" state because it is usually used to immediately present the user with the result of performing an action, even though the action actually takes time to complete. @@ -72,7 +80,11 @@ For example, when a user types a message into the form and hits the "Send" butto +<<<<<<< HEAD ```js App.js +======= +```js src/App.js +>>>>>>> 303ecae3dd4c7b570cf18e0115b94188f6aad5a1 import { useOptimistic, useState, useRef } from "react"; import { deliverMessage } from "./actions.js"; @@ -122,7 +134,11 @@ export default function App() { } ``` +<<<<<<< HEAD ```js actions.js +======= +```js src/actions.js +>>>>>>> 303ecae3dd4c7b570cf18e0115b94188f6aad5a1 export async function deliverMessage(message) { await new Promise((res) => setTimeout(res, 1000)); return message; diff --git a/src/content/reference/react/useReducer.md b/src/content/reference/react/useReducer.md index 3477660d2..dbd18f6b8 100644 --- a/src/content/reference/react/useReducer.md +++ b/src/content/reference/react/useReducer.md @@ -322,7 +322,7 @@ In this example, the reducer manages an array of tasks. The array needs to be up -```js App.js +```js src/App.js import { useReducer } from 'react'; import AddTask from './AddTask.js'; import TaskList from './TaskList.js'; @@ -405,7 +405,7 @@ const initialTasks = [ ]; ``` -```js AddTask.js hidden +```js src/AddTask.js hidden import { useState } from 'react'; export default function AddTask({ onAddTask }) { @@ -426,7 +426,7 @@ export default function AddTask({ onAddTask }) { } ``` -```js TaskList.js hidden +```js src/TaskList.js hidden import { useState } from 'react'; export default function TaskList({ @@ -515,7 +515,7 @@ If updating arrays and objects without mutation feels tedious, you can use a lib -```js App.js +```js src/App.js import { useImmerReducer } from 'use-immer'; import AddTask from './AddTask.js'; import TaskList from './TaskList.js'; @@ -597,7 +597,7 @@ const initialTasks = [ ]; ``` -```js AddTask.js hidden +```js src/AddTask.js hidden import { useState } from 'react'; export default function AddTask({ onAddTask }) { @@ -618,7 +618,7 @@ export default function AddTask({ onAddTask }) { } ``` -```js TaskList.js hidden +```js src/TaskList.js hidden import { useState } from 'react'; export default function TaskList({ @@ -763,7 +763,7 @@ This example passes the initializer function, so the `createInitialState` functi -```js App.js hidden +```js src/App.js hidden import TodoList from './TodoList.js'; export default function App() { @@ -771,7 +771,7 @@ export default function App() { } ``` -```js TodoList.js active +```js src/TodoList.js active import { useReducer } from 'react'; function createInitialState(username) { @@ -851,7 +851,7 @@ This example **does not** pass the initializer function, so the `createInitialSt -```js App.js hidden +```js src/App.js hidden import TodoList from './TodoList.js'; export default function App() { @@ -859,7 +859,7 @@ export default function App() { } ``` -```js TodoList.js active +```js src/TodoList.js active import { useReducer } from 'react'; function createInitialState(username) { diff --git a/src/content/reference/react/useState.md b/src/content/reference/react/useState.md index d23fa489b..ee86f0e8f 100644 --- a/src/content/reference/react/useState.md +++ b/src/content/reference/react/useState.md @@ -630,7 +630,7 @@ In this example, the `todos` state variable holds an array. Each button handler -```js App.js +```js src/App.js import { useState } from 'react'; import AddTodo from './AddTodo.js'; import TaskList from './TaskList.js'; @@ -687,7 +687,7 @@ export default function TaskApp() { } ``` -```js AddTodo.js +```js src/AddTodo.js import { useState } from 'react'; export default function AddTodo({ onAddTodo }) { @@ -708,7 +708,7 @@ export default function AddTodo({ onAddTodo }) { } ``` -```js TaskList.js +```js src/TaskList.js import { useState } from 'react'; export default function TaskList({ @@ -1028,7 +1028,7 @@ Read [preserving and resetting state](/learn/preserving-and-resetting-state) to -```js App.js +```js src/App.js import { useState } from 'react'; export default function App() { @@ -1083,7 +1083,7 @@ In the rare case that none of these apply, there is a pattern you can use to upd Here's an example. This `CountLabel` component displays the `count` prop passed to it: -```js CountLabel.js +```js src/CountLabel.js export default function CountLabel({ count }) { return

          {count}

          } @@ -1093,7 +1093,7 @@ Say you want to show whether the counter has *increased or decreased* since the -```js App.js +```js src/App.js import { useState } from 'react'; import CountLabel from './CountLabel.js'; @@ -1113,7 +1113,7 @@ export default function App() { } ``` -```js CountLabel.js active +```js src/CountLabel.js active import { useState } from 'react'; export default function CountLabel({ count }) { diff --git a/src/content/reference/react/useSyncExternalStore.md b/src/content/reference/react/useSyncExternalStore.md index cda2ec3fa..ebaf0987b 100644 --- a/src/content/reference/react/useSyncExternalStore.md +++ b/src/content/reference/react/useSyncExternalStore.md @@ -57,9 +57,9 @@ The current snapshot of the store which you can use in your rendering logic. * If a different `subscribe` function is passed during a re-render, React will re-subscribe to the store using the newly passed `subscribe` function. You can prevent this by declaring `subscribe` outside the component. -* If the store is mutated during a [non-blocking transition update](/reference/react/useTransition), React will fall back to performing that update as blocking. Specifically, React will call `getSnapshot` a second time just before applying changes to the DOM. If it returns a different value than when it was called originally, React will restart the transition update from scratch, this time applying it as a blocking update, to ensure that every component on screen is reflecting the same version of the store. +* If the store is mutated during a [non-blocking transition update](/reference/react/useTransition), React will fall back to performing that update as blocking. Specifically, for every transition update, React will call `getSnapshot` a second time just before applying changes to the DOM. If it returns a different value than when it was called originally, React will restart the update from scratch, this time applying it as a blocking update, to ensure that every component on screen is reflecting the same version of the store. -* It's not recommended to _suspend_ a render based on a store value returned by `useSyncExternalStore`. The reason is that mutations to the external store cannot be [marked as non-blocking transition updates](/reference/react/useTransition), so they will trigger the nearest [`Suspense` fallback](/reference/react/Suspense), replacing already-rendered content on screen with a loading spinner, which typically makes a poor UX. +* It's not recommended to _suspend_ a render based on a store value returned by `useSyncExternalStore`. The reason is that mutations to the external store cannot be marked as [non-blocking transition updates](/reference/react/useTransition), so they will trigger the nearest [`Suspense` fallback](/reference/react/Suspense), replacing already-rendered content on screen with a loading spinner, which typically makes a poor UX. For example, the following are discouraged: @@ -131,7 +131,7 @@ export default function TodosApp() { } ``` -```js todoStore.js +```js src/todoStore.js // This is an example of a third-party store // that you might need to integrate with React. @@ -300,7 +300,7 @@ export default function App() { } ``` -```js useOnlineStatus.js +```js src/useOnlineStatus.js import { useSyncExternalStore } from 'react'; export function useOnlineStatus() { diff --git a/src/content/reference/react/useTransition.md b/src/content/reference/react/useTransition.md index 672b448b6..b2d34d937 100644 --- a/src/content/reference/react/useTransition.md +++ b/src/content/reference/react/useTransition.md @@ -184,7 +184,7 @@ export default function TabContainer() { } ``` -```js TabButton.js +```js src/TabButton.js import { useTransition } from 'react'; export default function TabButton({ children, isActive, onClick }) { @@ -202,7 +202,7 @@ export default function TabButton({ children, isActive, onClick }) { ``` -```js AboutTab.js +```js src/AboutTab.js export default function AboutTab() { return (

          Welcome to my profile!

          @@ -210,7 +210,7 @@ export default function AboutTab() { } ``` -```js PostsTab.js +```js src/PostsTab.js import { memo } from 'react'; const PostsTab = memo(function PostsTab() { @@ -244,7 +244,7 @@ function SlowPost({ index }) { export default PostsTab; ``` -```js ContactTab.js +```js src/ContactTab.js export default function ContactTab() { return ( <> @@ -320,7 +320,7 @@ export default function TabContainer() { } ``` -```js TabButton.js +```js src/TabButton.js import { useTransition } from 'react'; export default function TabButton({ children, isActive, onClick }) { @@ -338,7 +338,7 @@ export default function TabButton({ children, isActive, onClick }) { ``` -```js AboutTab.js +```js src/AboutTab.js export default function AboutTab() { return (

          Welcome to my profile!

          @@ -346,7 +346,7 @@ export default function AboutTab() { } ``` -```js PostsTab.js +```js src/PostsTab.js import { memo } from 'react'; const PostsTab = memo(function PostsTab() { @@ -380,7 +380,7 @@ function SlowPost({ index }) { export default PostsTab; ``` -```js ContactTab.js +```js src/ContactTab.js export default function ContactTab() { return ( <> @@ -473,7 +473,7 @@ export default function TabContainer() { } ``` -```js TabButton.js active +```js src/TabButton.js active import { useTransition } from 'react'; export default function TabButton({ children, isActive, onClick }) { @@ -493,7 +493,7 @@ export default function TabButton({ children, isActive, onClick }) { } ``` -```js AboutTab.js +```js src/AboutTab.js export default function AboutTab() { return (

          Welcome to my profile!

          @@ -501,7 +501,7 @@ export default function AboutTab() { } ``` -```js PostsTab.js +```js src/PostsTab.js import { memo } from 'react'; const PostsTab = memo(function PostsTab() { @@ -535,7 +535,7 @@ function SlowPost({ index }) { export default PostsTab; ``` -```js ContactTab.js +```js src/ContactTab.js export default function ContactTab() { return ( <> @@ -616,7 +616,7 @@ export default function TabContainer() { } ``` -```js TabButton.js active +```js src/TabButton.js active import { useTransition } from 'react'; export default function TabButton({ children, isActive, onClick }) { @@ -639,7 +639,7 @@ export default function TabButton({ children, isActive, onClick }) { } ``` -```js AboutTab.js +```js src/AboutTab.js export default function AboutTab() { return (

          Welcome to my profile!

          @@ -647,7 +647,7 @@ export default function AboutTab() { } ``` -```js PostsTab.js +```js src/PostsTab.js import { memo } from 'react'; const PostsTab = memo(function PostsTab() { @@ -681,7 +681,7 @@ function SlowPost({ index }) { export default PostsTab; ``` -```js ContactTab.js +```js src/ContactTab.js export default function ContactTab() { return ( <> @@ -751,7 +751,7 @@ export default function TabContainer() { } ``` -```js TabButton.js +```js src/TabButton.js export default function TabButton({ children, isActive, onClick }) { if (isActive) { return {children} @@ -766,7 +766,7 @@ export default function TabButton({ children, isActive, onClick }) { } ``` -```js AboutTab.js hidden +```js src/AboutTab.js hidden export default function AboutTab() { return (

          Welcome to my profile!

          @@ -774,7 +774,7 @@ export default function AboutTab() { } ``` -```js PostsTab.js hidden +```js src/PostsTab.js hidden import { fetchData } from './data.js'; // Note: this component is written using an experimental API @@ -830,7 +830,7 @@ function use(promise) { } ``` -```js ContactTab.js hidden +```js src/ContactTab.js hidden export default function ContactTab() { return ( <> @@ -847,7 +847,7 @@ export default function ContactTab() { ``` -```js data.js hidden +```js src/data.js hidden // Note: the way you would do data fetching depends on // the framework that you use together with Suspense. // Normally, the caching logic would be inside a framework. @@ -937,7 +937,7 @@ export default function TabContainer() { } ``` -```js TabButton.js active +```js src/TabButton.js active import { useTransition } from 'react'; export default function TabButton({ children, isActive, onClick }) { @@ -960,7 +960,7 @@ export default function TabButton({ children, isActive, onClick }) { } ``` -```js AboutTab.js hidden +```js src/AboutTab.js hidden export default function AboutTab() { return (

          Welcome to my profile!

          @@ -968,7 +968,7 @@ export default function AboutTab() { } ``` -```js PostsTab.js hidden +```js src/PostsTab.js hidden import { fetchData } from './data.js'; // Note: this component is written using an experimental API @@ -1024,7 +1024,7 @@ function use(promise) { } ``` -```js ContactTab.js hidden +```js src/ContactTab.js hidden export default function ContactTab() { return ( <> @@ -1041,7 +1041,7 @@ export default function ContactTab() { ``` -```js data.js hidden +```js src/data.js hidden // Note: the way you would do data fetching depends on // the framework that you use together with Suspense. // Normally, the caching logic would be inside a framework. @@ -1138,7 +1138,7 @@ Here is a tiny simplified router example using transitions for navigations. } ``` -```js App.js +```js src/App.js import { Suspense, useState, useTransition } from 'react'; import IndexPage from './IndexPage.js'; import ArtistPage from './ArtistPage.js'; @@ -1189,7 +1189,7 @@ function BigSpinner() { } ``` -```js Layout.js +```js src/Layout.js export default function Layout({ children, isPending }) { return (
          @@ -1206,7 +1206,7 @@ export default function Layout({ children, isPending }) { } ``` -```js IndexPage.js +```js src/IndexPage.js export default function IndexPage({ navigate }) { return (