diff --git a/src/components/Layout/Sidebar/SidebarLink.tsx b/src/components/Layout/Sidebar/SidebarLink.tsx index 5c01fefc..9650e95f 100644 --- a/src/components/Layout/Sidebar/SidebarLink.tsx +++ b/src/components/Layout/Sidebar/SidebarLink.tsx @@ -24,7 +24,7 @@ interface SidebarLinkProps { selected?: boolean; title: string; level: number; - version?: 'canary' | 'major' | 'experimental'; + version?: 'canary' | 'major' | 'experimental' | 'rc'; icon?: React.ReactNode; isExpanded?: boolean; hideArrow?: boolean; @@ -102,6 +102,12 @@ export function SidebarLink({ className="ms-1 text-gray-30 dark:text-gray-60 inline-block w-3.5 h-3.5 align-[-3px]" /> )} + {version === 'rc' && ( + + )} {isExpanded != null && !hideArrow && ( diff --git a/src/components/MDX/ExpandableCallout.tsx b/src/components/MDX/ExpandableCallout.tsx index ba93d3e2..5b7491e1 100644 --- a/src/components/MDX/ExpandableCallout.tsx +++ b/src/components/MDX/ExpandableCallout.tsx @@ -24,6 +24,7 @@ type CalloutVariants = | 'wip' | 'canary' | 'experimental' + | 'rc' | 'major' | 'rsc'; @@ -50,6 +51,15 @@ const variantMap = { overlayGradient: 'linear-gradient(rgba(245, 249, 248, 0), rgba(245, 249, 248, 1)', }, + rc: { + title: 'RC', + Icon: IconCanary, + containerClasses: + 'bg-gray-5 dark:bg-gray-60 dark:bg-opacity-20 text-primary dark:text-primary-dark text-lg', + textColor: 'text-gray-60 dark:text-gray-30', + overlayGradient: + 'linear-gradient(rgba(245, 249, 248, 0), rgba(245, 249, 248, 1)', + }, canary: { title: 'Canary', Icon: IconCanary, diff --git a/src/components/MDX/MDXComponents.tsx b/src/components/MDX/MDXComponents.tsx index 7a258370..a32dad27 100644 --- a/src/components/MDX/MDXComponents.tsx +++ b/src/components/MDX/MDXComponents.tsx @@ -106,6 +106,10 @@ const Canary = ({children}: {children: React.ReactNode}) => ( {children} ); +const RC = ({children}: {children: React.ReactNode}) => ( + {children} +); + const Experimental = ({children}: {children: React.ReactNode}) => ( {children} ); @@ -533,6 +537,7 @@ export const MDXComponents = { Math, MathI, Note, + RC, Canary, Experimental, ExperimentalBadge, diff --git a/src/components/PageHeading.tsx b/src/components/PageHeading.tsx index e3798664..85f095ff 100644 --- a/src/components/PageHeading.tsx +++ b/src/components/PageHeading.tsx @@ -19,7 +19,7 @@ import {IconExperimental} from './Icon/IconExperimental'; interface PageHeadingProps { title: string; - version?: 'experimental' | 'canary'; + version?: 'experimental' | 'canary' | 'rc'; experimental?: boolean; status?: string; description?: string; @@ -47,6 +47,12 @@ function PageHeading({ className="ms-4 mt-1 text-gray-50 dark:text-gray-40 inline-block w-6 h-6 align-[-1px]" /> )} + {version === 'rc' && ( + + )} {version === 'experimental' && ( { }); // compiler inserted dependencies. ``` -With this code, the React Compiler can infer the dependencies for you and insert them automatically so you don't need to see or write them. With features like [the IDE extension](#compiler-ide-extension) and [`useEffectEvent`](/reference/react/experimental_useEffectEvent), we can provide a CodeLens to show you what the Compiler inserted for times you need to debug, or to optimize by removing a dependency. This helps reinforce the correct mental model for writing Effects, which can run at any time to synchronize your component or hook's state with something else. +With this code, the React Compiler can infer the dependencies for you and insert them automatically so you don't need to see or write them. With features like [the IDE extension](#compiler-ide-extension) and [`useEffectEvent`](/reference/react/useEffectEvent), we can provide a CodeLens to show you what the Compiler inserted for times you need to debug, or to optimize by removing a dependency. This helps reinforce the correct mental model for writing Effects, which can run at any time to synchronize your component or hook's state with something else. Our hope is that automatically inserting dependencies is not only easier to write, but that it also makes them easier to understand by forcing you to think in terms of what the Effect does, and not in component lifecycles. diff --git a/src/content/learn/escape-hatches.md b/src/content/learn/escape-hatches.md index 0b2d595b..e6b050e0 100644 --- a/src/content/learn/escape-hatches.md +++ b/src/content/learn/escape-hatches.md @@ -455,8 +455,8 @@ This is not ideal. You want to re-connect to the chat only if the `roomId` has c ```json package.json hidden { "dependencies": { - "react": "experimental", - "react-dom": "experimental", + "react": "canary", + "react-dom": "canary", "react-scripts": "latest", "toastify-js": "1.12.0" }, @@ -471,7 +471,7 @@ This is not ideal. You want to re-connect to the chat only if the `roomId` has c ```js import { useState, useEffect } from 'react'; -import { experimental_useEffectEvent as useEffectEvent } from 'react'; +import { useEffectEvent } from 'react'; import { createConnection, sendMessage } from './chat.js'; import { showNotification } from './notifications.js'; diff --git a/src/content/learn/removing-effect-dependencies.md b/src/content/learn/removing-effect-dependencies.md index 7ab6dbc1..fb98a0cd 100644 --- a/src/content/learn/removing-effect-dependencies.md +++ b/src/content/learn/removing-effect-dependencies.md @@ -609,11 +609,13 @@ function ChatRoom({ roomId }) { ### Do you want to read a value without "reacting" to its changes? {/*do-you-want-to-read-a-value-without-reacting-to-its-changes*/} - + -This section describes an **experimental API that has not yet been released** in a stable version of React. +**The `useEffectEvent` API 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) + + Suppose that you want to play a sound when the user receives a new message unless `isMuted` is `true`: @@ -1262,8 +1264,8 @@ Is there a line of code inside the Effect that should not be reactive? How can y ```json package.json hidden { "dependencies": { - "react": "experimental", - "react-dom": "experimental", + "react": "canary", + "react-dom": "canary", "react-scripts": "latest" }, "scripts": { @@ -1277,7 +1279,7 @@ Is there a line of code inside the Effect that should not be reactive? How can y ```js import { useState, useEffect, useRef } from 'react'; -import { experimental_useEffectEvent as useEffectEvent } from 'react'; +import { useEffectEvent } from 'react'; import { FadeInAnimation } from './animation.js'; function Welcome({ duration }) { @@ -1389,8 +1391,8 @@ Your Effect needs to read the latest value of `duration`, but you don't want it ```json package.json hidden { "dependencies": { - "react": "experimental", - "react-dom": "experimental", + "react": "canary", + "react-dom": "canary", "react-scripts": "latest" }, "scripts": { @@ -1405,7 +1407,7 @@ Your Effect needs to read the latest value of `duration`, but you don't want it ```js import { useState, useEffect, useRef } from 'react'; import { FadeInAnimation } from './animation.js'; -import { experimental_useEffectEvent as useEffectEvent } from 'react'; +import { useEffectEvent } from 'react'; function Welcome({ duration }) { const ref = useRef(null); @@ -1825,8 +1827,8 @@ Another of these functions only exists to pass some state to an imported API met ```json package.json hidden { "dependencies": { - "react": "experimental", - "react-dom": "experimental", + "react": "canary", + "react-dom": "canary", "react-scripts": "latest", "toastify-js": "1.12.0" }, @@ -1907,7 +1909,7 @@ export default function App() { ```js src/ChatRoom.js active import { useState, useEffect } from 'react'; -import { experimental_useEffectEvent as useEffectEvent } from 'react'; +import { useEffectEvent } from 'react'; export default function ChatRoom({ roomId, createConnection, onMessage }) { useEffect(() => { @@ -2120,8 +2122,8 @@ As a result, the chat re-connects only when something meaningful (`roomId` or `i ```json package.json hidden { "dependencies": { - "react": "experimental", - "react-dom": "experimental", + "react": "canary", + "react-dom": "canary", "react-scripts": "latest", "toastify-js": "1.12.0" }, @@ -2189,7 +2191,7 @@ export default function App() { ```js src/ChatRoom.js active import { useState, useEffect } from 'react'; -import { experimental_useEffectEvent as useEffectEvent } from 'react'; +import { useEffectEvent } from 'react'; import { createEncryptedConnection, createUnencryptedConnection, diff --git a/src/content/learn/reusing-logic-with-custom-hooks.md b/src/content/learn/reusing-logic-with-custom-hooks.md index de68dd19..2038e59e 100644 --- a/src/content/learn/reusing-logic-with-custom-hooks.md +++ b/src/content/learn/reusing-logic-with-custom-hooks.md @@ -837,11 +837,13 @@ Every time your `ChatRoom` component re-renders, it passes the latest `roomId` a ### Passing event handlers to custom Hooks {/*passing-event-handlers-to-custom-hooks*/} - + -This section describes an **experimental API that has not yet been released** in a stable version of React. +**The `useEffectEvent` API 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) + + As you start using `useChatRoom` in more components, you might want to let components customize its behavior. For example, currently, the logic for what to do when a message arrives is hardcoded inside the Hook: @@ -985,7 +987,7 @@ export default function ChatRoom({ roomId }) { ```js src/useChatRoom.js import { useEffect } from 'react'; -import { experimental_useEffectEvent as useEffectEvent } from 'react'; +import { useEffectEvent } from 'react'; import { createConnection } from './chat.js'; export function useChatRoom({ serverUrl, roomId, onReceiveMessage }) { @@ -1070,8 +1072,8 @@ export function showNotification(message, theme = 'dark') { ```json package.json hidden { "dependencies": { - "react": "experimental", - "react-dom": "experimental", + "react": "canary", + "react-dom": "canary", "react-scripts": "latest", "toastify-js": "1.12.0" }, @@ -1666,7 +1668,7 @@ export default function App() { ```js src/useFadeIn.js active import { useState, useEffect } from 'react'; -import { experimental_useEffectEvent as useEffectEvent } from 'react'; +import { useEffectEvent } from 'react'; export function useFadeIn(ref, duration) { const [isRunning, setIsRunning] = useState(true); @@ -1719,8 +1721,8 @@ html, body { min-height: 300px; } ```json package.json hidden { "dependencies": { - "react": "experimental", - "react-dom": "experimental", + "react": "canary", + "react-dom": "canary", "react-scripts": "latest" }, "scripts": { @@ -2208,8 +2210,8 @@ It looks like your `useInterval` Hook accepts an event listener as an argument. ```json package.json hidden { "dependencies": { - "react": "experimental", - "react-dom": "experimental", + "react": "canary", + "react-dom": "canary", "react-scripts": "latest" }, "scripts": { @@ -2252,7 +2254,7 @@ export function useCounter(delay) { ```js src/useInterval.js import { useEffect } from 'react'; -import { experimental_useEffectEvent as useEffectEvent } from 'react'; +import { useEffectEvent } from 'react'; export function useInterval(onTick, delay) { useEffect(() => { @@ -2279,8 +2281,8 @@ With this change, both intervals work as expected and don't interfere with each ```json package.json hidden { "dependencies": { - "react": "experimental", - "react-dom": "experimental", + "react": "canary", + "react-dom": "canary", "react-scripts": "latest" }, "scripts": { @@ -2324,7 +2326,7 @@ export function useCounter(delay) { ```js src/useInterval.js active import { useEffect } from 'react'; -import { experimental_useEffectEvent as useEffectEvent } from 'react'; +import { useEffectEvent } from 'react'; export function useInterval(callback, delay) { const onTick = useEffectEvent(callback); diff --git a/src/content/learn/separating-events-from-effects.md b/src/content/learn/separating-events-from-effects.md index fd603c39..2a19e0f1 100644 --- a/src/content/learn/separating-events-from-effects.md +++ b/src/content/learn/separating-events-from-effects.md @@ -400,13 +400,15 @@ You need a way to separate this non-reactive logic from the reactive Effect arou ### Declaring an Effect Event {/*declaring-an-effect-event*/} - + -This section describes an **experimental API that has not yet been released** in a stable version of React. +**The `useEffectEvent` API 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) -Use a special Hook called [`useEffectEvent`](/reference/react/experimental_useEffectEvent) to extract this non-reactive logic out of your Effect: + + +Use a special Hook called [`useEffectEvent`](/reference/react/useEffectEvent) to extract this non-reactive logic out of your Effect: ```js {1,4-6} import { useEffect, useEffectEvent } from 'react'; @@ -448,8 +450,8 @@ Verify that the new behavior works as you would expect: ```json package.json hidden { "dependencies": { - "react": "experimental", - "react-dom": "experimental", + "react": "canary", + "react-dom": "canary", "react-scripts": "latest", "toastify-js": "1.12.0" }, @@ -464,7 +466,7 @@ Verify that the new behavior works as you would expect: ```js import { useState, useEffect } from 'react'; -import { experimental_useEffectEvent as useEffectEvent } from 'react'; +import { useEffectEvent } from 'react'; import { createConnection, sendMessage } from './chat.js'; import { showNotification } from './notifications.js'; @@ -578,11 +580,13 @@ You can think of Effect Events as being very similar to event handlers. The main ### Reading latest props and state with Effect Events {/*reading-latest-props-and-state-with-effect-events*/} - + + +**The `useEffectEvent` API is currently only available in React’s Canary and Experimental channels.** -This section describes an **experimental API that has not yet been released** in a stable version of React. +[Learn more about React’s release channels here.](/community/versioning-policy#all-release-channels) - + Effect Events let you fix many patterns where you might be tempted to suppress the dependency linter. @@ -803,8 +807,8 @@ With `useEffectEvent`, there is no need to "lie" to the linter, and the code wor ```json package.json hidden { "dependencies": { - "react": "experimental", - "react-dom": "experimental", + "react": "canary", + "react-dom": "canary", "react-scripts": "latest" }, "scripts": { @@ -818,7 +822,7 @@ With `useEffectEvent`, there is no need to "lie" to the linter, and the code wor ```js import { useState, useEffect } from 'react'; -import { experimental_useEffectEvent as useEffectEvent } from 'react'; +import { useEffectEvent } from 'react'; export default function App() { const [position, setPosition] = useState({ x: 0, y: 0 }); @@ -878,11 +882,13 @@ Read [Removing Effect Dependencies](/learn/removing-effect-dependencies) for oth ### Limitations of Effect Events {/*limitations-of-effect-events*/} - + + +**The `useEffectEvent` API is currently only available in React’s Canary and Experimental channels.** -This section describes an **experimental API that has not yet been released** in a stable version of React. +[Learn more about React’s release channels here.](/community/versioning-policy#all-release-channels) - + Effect Events are very limited in how you can use them: @@ -976,8 +982,8 @@ To fix this code, it's enough to follow the rules. ```json package.json hidden { "dependencies": { - "react": "experimental", - "react-dom": "experimental", + "react": "canary", + "react-dom": "canary", "react-scripts": "latest" }, "scripts": { @@ -1046,8 +1052,8 @@ If you remove the suppression comment, React will tell you that this Effect's co ```json package.json hidden { "dependencies": { - "react": "experimental", - "react-dom": "experimental", + "react": "canary", + "react-dom": "canary", "react-scripts": "latest" }, "scripts": { @@ -1124,8 +1130,8 @@ It seems like the Effect which sets up the timer "reacts" to the `increment` val ```json package.json hidden { "dependencies": { - "react": "experimental", - "react-dom": "experimental", + "react": "canary", + "react-dom": "canary", "react-scripts": "latest" }, "scripts": { @@ -1139,7 +1145,7 @@ It seems like the Effect which sets up the timer "reacts" to the `increment` val ```js import { useState, useEffect } from 'react'; -import { experimental_useEffectEvent as useEffectEvent } from 'react'; +import { useEffectEvent } from 'react'; export default function Timer() { const [count, setCount] = useState(0); @@ -1193,8 +1199,8 @@ To solve the issue, extract an `onTick` Effect Event from the Effect: ```json package.json hidden { "dependencies": { - "react": "experimental", - "react-dom": "experimental", + "react": "canary", + "react-dom": "canary", "react-scripts": "latest" }, "scripts": { @@ -1208,7 +1214,7 @@ To solve the issue, extract an `onTick` Effect Event from the Effect: ```js import { useState, useEffect } from 'react'; -import { experimental_useEffectEvent as useEffectEvent } from 'react'; +import { useEffectEvent } from 'react'; export default function Timer() { const [count, setCount] = useState(0); @@ -1275,8 +1281,8 @@ Code inside Effect Events is not reactive. Are there cases in which you would _w ```json package.json hidden { "dependencies": { - "react": "experimental", - "react-dom": "experimental", + "react": "canary", + "react-dom": "canary", "react-scripts": "latest" }, "scripts": { @@ -1290,7 +1296,7 @@ Code inside Effect Events is not reactive. Are there cases in which you would _w ```js import { useState, useEffect } from 'react'; -import { experimental_useEffectEvent as useEffectEvent } from 'react'; +import { useEffectEvent } from 'react'; export default function Timer() { const [count, setCount] = useState(0); @@ -1362,8 +1368,8 @@ The problem with the above example is that it extracted an Effect Event called ` ```json package.json hidden { "dependencies": { - "react": "experimental", - "react-dom": "experimental", + "react": "canary", + "react-dom": "canary", "react-scripts": "latest" }, "scripts": { @@ -1377,7 +1383,7 @@ The problem with the above example is that it extracted an Effect Event called ` ```js import { useState, useEffect } from 'react'; -import { experimental_useEffectEvent as useEffectEvent } from 'react'; +import { useEffectEvent } from 'react'; export default function Timer() { const [count, setCount] = useState(0); @@ -1458,8 +1464,8 @@ Your Effect knows which room it connected to. Is there any information that you ```json package.json hidden { "dependencies": { - "react": "experimental", - "react-dom": "experimental", + "react": "canary", + "react-dom": "canary", "react-scripts": "latest", "toastify-js": "1.12.0" }, @@ -1474,7 +1480,7 @@ Your Effect knows which room it connected to. Is there any information that you ```js import { useState, useEffect } from 'react'; -import { experimental_useEffectEvent as useEffectEvent } from 'react'; +import { useEffectEvent } from 'react'; import { createConnection, sendMessage } from './chat.js'; import { showNotification } from './notifications.js'; @@ -1599,8 +1605,8 @@ To fix the issue, instead of reading the *latest* `roomId` inside the Effect Eve ```json package.json hidden { "dependencies": { - "react": "experimental", - "react-dom": "experimental", + "react": "canary", + "react-dom": "canary", "react-scripts": "latest", "toastify-js": "1.12.0" }, @@ -1615,7 +1621,7 @@ To fix the issue, instead of reading the *latest* `roomId` inside the Effect Eve ```js import { useState, useEffect } from 'react'; -import { experimental_useEffectEvent as useEffectEvent } from 'react'; +import { useEffectEvent } from 'react'; import { createConnection, sendMessage } from './chat.js'; import { showNotification } from './notifications.js'; @@ -1736,8 +1742,8 @@ To solve the additional challenge, save the notification timeout ID and clear it ```json package.json hidden { "dependencies": { - "react": "experimental", - "react-dom": "experimental", + "react": "canary", + "react-dom": "canary", "react-scripts": "latest", "toastify-js": "1.12.0" }, @@ -1752,7 +1758,7 @@ To solve the additional challenge, save the notification timeout ID and clear it ```js import { useState, useEffect } from 'react'; -import { experimental_useEffectEvent as useEffectEvent } from 'react'; +import { useEffectEvent } from 'react'; import { createConnection, sendMessage } from './chat.js'; import { showNotification } from './notifications.js'; diff --git a/src/content/learn/tutorial-tic-tac-toe.md b/src/content/learn/tutorial-tic-tac-toe.md index ec8d0f61..f25754be 100644 --- a/src/content/learn/tutorial-tic-tac-toe.md +++ b/src/content/learn/tutorial-tic-tac-toe.md @@ -283,9 +283,15 @@ Katika CodeSandbox utaona sehemu tatu kuu: ![CodeSandbox na msimbo wa mwanzo](../images/tutorial/react-starter-code-codesandbox.png) +<<<<<<< HEAD 1. Sehemu ya _Files_ na orodha ya mafaili kama `App.js`, `index.js`, `styles.css` na folda inayoitwa `public` 1. _Kihariri cha msimbo_ ambapo utaona msimbo wa chanzo wa faili uliyouchagua 1. Sehemu ya _kivinjari_ ambapo utaona jinsi msimbo ulioandika utakavyonyeshwa +======= +1. The _Files_ section with a list of files like `App.js`, `index.js`, `styles.css` in `src` folder and a folder called `public` +1. The _code editor_ where you'll see the source code of your selected file +1. The _browser_ section where you'll see how the code you've written will be displayed +>>>>>>> 49c2d26722fb1b5865ce0221a4cadc71b615e4cf Faili ya `App.js` inapaswa kuchaguliwa katika sehemu ya _Files_. Maudhui ya faili hiyo katika _mhariri wa msimbo_ yanapaswa kuwa: @@ -2247,7 +2253,11 @@ body { +<<<<<<< HEAD Unapozunguka kupitia orodha ya `history` ndani ya function unayopitisha kwa `map`, hoja ya `squares` inapitia kila kipengele cha `history`, na hoja ya `move` inapitia kila kiashiria cha orodha: `0`, `1`, `2`, …. (Katika hali nyingi, ungehitaji vipengele halisi vya orodha, lakini ili kuonyesha orodha ya harakati utahitaji tu viashiria.) +======= +As you iterate through the `history` array inside the function you passed to `map`, the `squares` argument goes through each element of `history`, and the `move` argument goes through each array index: `0`, `1`, `2`, …. (In most cases, you'd need the actual array elements, but to render a list of moves you will only need indexes.) +>>>>>>> 49c2d26722fb1b5865ce0221a4cadc71b615e4cf Kwa kila harakati katika historia ya mchezo wa tic-tac-toe, unaunda kipengele cha orodha `
  • ` kinachojumuisha kitufe `