From a30e1f954dce2a67985caa8b2376a1839dbfa6cf Mon Sep 17 00:00:00 2001 From: Brandon Dail Date: Mon, 10 Jul 2023 03:26:39 -0500 Subject: [PATCH 001/106] update link to fault tolerance blog post (#6142) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit this is the canonical link now 🫡 --- src/content/reference/react/Component.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/content/reference/react/Component.md b/src/content/reference/react/Component.md index 006ade5d8..569bf19f2 100644 --- a/src/content/reference/react/Component.md +++ b/src/content/reference/react/Component.md @@ -1393,7 +1393,7 @@ Then you can wrap a part of your component tree with it: If `Profile` or its child component throws an error, `ErrorBoundary` will "catch" that error, display a fallback UI with the error message you've provided, and send a production error report to your error reporting service. -You don't need to wrap every component into a separate error boundary. When you think about the [granularity of error boundaries,](https://aweary.dev/fault-tolerance-react/) consider where it makes sense to display an error message. For example, in a messaging app, it makes sense to place an error boundary around the list of conversations. It also makes sense to place one around every individual message. However, it wouldn't make sense to place a boundary around every avatar. +You don't need to wrap every component into a separate error boundary. When you think about the [granularity of error boundaries,](https://www.brandondail.com/posts/fault-tolerance-react) consider where it makes sense to display an error message. For example, in a messaging app, it makes sense to place an error boundary around the list of conversations. It also makes sense to place one around every individual message. However, it wouldn't make sense to place a boundary around every avatar. From b9eea4da28db66591ae5935898f98acdf009a0ad Mon Sep 17 00:00:00 2001 From: Ricky Date: Fri, 21 Jul 2023 19:24:36 -0400 Subject: [PATCH 002/106] Fix lint warnings (#6174) --- .eslintrc | 3 +- src/components/Layout/HomeContent.js | 32 +++++++------------ src/components/Layout/Sidebar/SidebarLink.tsx | 1 + .../Layout/SidebarNav/SidebarNav.tsx | 1 - src/components/Layout/TopNav/TopNav.tsx | 3 +- src/components/Layout/getRouteMeta.tsx | 2 +- src/components/MDX/BlogCard.tsx | 1 + src/components/MDX/MDXComponents.tsx | 3 +- src/components/MDX/Sandpack/CustomPreset.tsx | 1 - src/components/MDX/Sandpack/NavigationBar.tsx | 8 +++-- src/components/MDX/Sandpack/Preview.tsx | 1 - src/components/MDX/TeamMember.tsx | 1 - src/components/Search.tsx | 3 +- src/hooks/usePendingRoute.ts | 2 +- 14 files changed, 27 insertions(+), 35 deletions(-) diff --git a/.eslintrc b/.eslintrc index 147e54607..f617dea26 100644 --- a/.eslintrc +++ b/.eslintrc @@ -5,7 +5,8 @@ "plugins": ["@typescript-eslint"], "rules": { "no-unused-vars": "off", - "@typescript-eslint/no-unused-vars": "warn" + "@typescript-eslint/no-unused-vars": ["error", { "varsIgnorePattern": "^_" }], + "react-hooks/exhaustive-deps": "error" }, "env": { "node": true, diff --git a/src/components/Layout/HomeContent.js b/src/components/Layout/HomeContent.js index ba3ff6ef1..e1b1b440d 100644 --- a/src/components/Layout/HomeContent.js +++ b/src/components/Layout/HomeContent.js @@ -8,12 +8,10 @@ import { useState, useContext, useId, - Fragment, Suspense, useEffect, useRef, useTransition, - useReducer, } from 'react'; import cn from 'classnames'; import NextLink from 'next/link'; @@ -26,7 +24,6 @@ import {IconSearch} from 'components/Icon/IconSearch'; import {Logo} from 'components/Logo'; import Link from 'components/MDX/Link'; import CodeBlock from 'components/MDX/CodeBlock'; -import {IconNavArrow} from 'components/Icon/IconNavArrow'; import {ExternalLink} from 'components/ExternalLink'; import sidebarBlog from '../../sidebarBlog.json'; @@ -67,14 +64,6 @@ function Para({children}) { ); } -function Left({children}) { - return ( -
- {children} -
- ); -} - function Center({children}) { return (
@@ -90,19 +79,23 @@ function FullBleed({children}) { } function CurrentTime() { - const msPerMinute = 60 * 1000; - const date = new Date(); - let nextMinute = Math.floor(+date / msPerMinute + 1) * msPerMinute; - + const [date, setDate] = useState(new Date()); const currentTime = date.toLocaleTimeString([], { hour: 'numeric', minute: 'numeric', }); - let [, forceUpdate] = useReducer((n) => n + 1, 0); useEffect(() => { - const timeout = setTimeout(forceUpdate, nextMinute - Date.now()); + const msPerMinute = 60 * 1000; + let nextMinute = Math.floor(+date / msPerMinute + 1) * msPerMinute; + + const timeout = setTimeout(() => { + if (Date.now() > nextMinute) { + setDate(new Date()); + } + }, nextMinute - Date.now()); return () => clearTimeout(timeout); }, [date]); + return {currentTime}; } @@ -831,7 +824,7 @@ function ExampleLayout({ .filter((s) => s !== null); setOverlayStyles(nextOverlayStyles); } - }, [activeArea]); + }, [activeArea, hoverTopOffset]); return (
@@ -1211,7 +1204,7 @@ function useNestedScrollLock(ref) { window.removeEventListener('scroll', handleScroll); clearInterval(interval); }; - }, []); + }, [ref]); } function ExamplePanel({ @@ -1220,7 +1213,6 @@ function ExamplePanel({ noShadow, height, contentMarginTop, - activeArea, }) { return (
0 ? breadcrumbs : [routeTree], diff --git a/src/components/MDX/BlogCard.tsx b/src/components/MDX/BlogCard.tsx index ba610b111..1a16013a2 100644 --- a/src/components/MDX/BlogCard.tsx +++ b/src/components/MDX/BlogCard.tsx @@ -18,6 +18,7 @@ function BlogCard({title, badge, date, icon, url, children}: BlogCardProps) { return (
diff --git a/src/components/MDX/MDXComponents.tsx b/src/components/MDX/MDXComponents.tsx index ba531c9f0..8ddf371c9 100644 --- a/src/components/MDX/MDXComponents.tsx +++ b/src/components/MDX/MDXComponents.tsx @@ -369,7 +369,8 @@ function YouTubeIframe(props: any) { } function Image(props: any) { - return ; + const {alt, ...rest} = props; + return {alt}; } export const MDXComponents = { diff --git a/src/components/MDX/Sandpack/CustomPreset.tsx b/src/components/MDX/Sandpack/CustomPreset.tsx index 6e0862564..46e0ca255 100644 --- a/src/components/MDX/Sandpack/CustomPreset.tsx +++ b/src/components/MDX/Sandpack/CustomPreset.tsx @@ -54,7 +54,6 @@ export const CustomPreset = memo(function CustomPreset({ const SandboxShell = memo(function SandboxShell({ showDevTools, - onDevToolsLoad, devToolsLoaded, providedFiles, lintErrors, diff --git a/src/components/MDX/Sandpack/NavigationBar.tsx b/src/components/MDX/Sandpack/NavigationBar.tsx index 8c884a5d8..94e2eb4b3 100644 --- a/src/components/MDX/Sandpack/NavigationBar.tsx +++ b/src/components/MDX/Sandpack/NavigationBar.tsx @@ -90,15 +90,17 @@ export function NavigationBar({providedFiles}: {providedFiles: Array}) { } else { return; } - }, [isMultiFile]); + + // Note: in a real useEvent, onContainerResize would be omitted. + }, [isMultiFile, onContainerResize]); const handleReset = () => { /** * resetAllFiles must come first, otherwise - * the previous content will appears for a second + * the previous content will appear for a second * when the iframe loads. * - * Plus, it should only prompts if there's any file changes + * Plus, it should only prompt if there's any file changes */ if ( sandpack.editorState === 'dirty' && diff --git a/src/components/MDX/Sandpack/Preview.tsx b/src/components/MDX/Sandpack/Preview.tsx index 2e140360c..6b7a6d183 100644 --- a/src/components/MDX/Sandpack/Preview.tsx +++ b/src/components/MDX/Sandpack/Preview.tsx @@ -49,7 +49,6 @@ export function Preview({ errorScreenRegisteredRef, openInCSBRegisteredRef, loadingScreenRegisteredRef, - status, } = sandpack; if ( diff --git a/src/components/MDX/TeamMember.tsx b/src/components/MDX/TeamMember.tsx index 887e9f691..0db067e10 100644 --- a/src/components/MDX/TeamMember.tsx +++ b/src/components/MDX/TeamMember.tsx @@ -7,7 +7,6 @@ import Image from 'next/image'; import {IconTwitter} from '../Icon/IconTwitter'; import {IconGitHub} from '../Icon/IconGitHub'; import {ExternalLink} from '../ExternalLink'; -import {IconNewPage} from 'components/Icon/IconNewPage'; import {H3} from './Heading'; import {IconLink} from 'components/Icon/IconLink'; diff --git a/src/components/Search.tsx b/src/components/Search.tsx index 2a9743ec3..8bc47297a 100644 --- a/src/components/Search.tsx +++ b/src/components/Search.tsx @@ -5,11 +5,10 @@ import Head from 'next/head'; import Link from 'next/link'; import Router from 'next/router'; -import {lazy, useCallback, useEffect} from 'react'; +import {lazy, useEffect} from 'react'; import * as React from 'react'; import {createPortal} from 'react-dom'; import {siteConfig} from 'siteConfig'; -import cn from 'classnames'; export interface SearchProps { appId?: string; diff --git a/src/hooks/usePendingRoute.ts b/src/hooks/usePendingRoute.ts index 73ff0b8af..229a36e64 100644 --- a/src/hooks/usePendingRoute.ts +++ b/src/hooks/usePendingRoute.ts @@ -33,7 +33,7 @@ const usePendingRoute = () => { events.off('routeChangeComplete', handleRouteChangeComplete); clearTimeout(routeTransitionTimer); }; - }, []); + }, [events]); return pendingRoute; }; From d86cfc47634a3a3b94f683e99075b9815ac35a30 Mon Sep 17 00:00:00 2001 From: Ricky Date: Mon, 24 Jul 2023 10:05:08 -0400 Subject: [PATCH 003/106] Update useInsertionEffect docs (#6172) --- src/content/reference/react/useInsertionEffect.md | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/src/content/reference/react/useInsertionEffect.md b/src/content/reference/react/useInsertionEffect.md index 175b4476f..0238facf7 100644 --- a/src/content/reference/react/useInsertionEffect.md +++ b/src/content/reference/react/useInsertionEffect.md @@ -10,7 +10,7 @@ title: useInsertionEffect -`useInsertionEffect` is a version of [`useEffect`](/reference/react/useEffect) that fires before any DOM mutations. +`useInsertionEffect` allows inserting elements into the DOM before any layout effects fire. ```js useInsertionEffect(setup, dependencies?) @@ -26,7 +26,7 @@ useInsertionEffect(setup, dependencies?) ### `useInsertionEffect(setup, dependencies?)` {/*useinsertioneffect*/} -Call `useInsertionEffect` to insert the styles before any DOM mutations: +Call `useInsertionEffect` to insert styles before any effects fire that may need to read layout: ```js import { useInsertionEffect } from 'react'; @@ -44,7 +44,7 @@ function useCSS(rule) { #### Parameters {/*parameters*/} -* `setup`: The function with your Effect's logic. Your setup function may also optionally return a *cleanup* function. Before your component is added to the DOM, React will run your setup function. After every re-render with changed dependencies, React will first run the cleanup function (if you provided it) with the old values, and then run your setup function with the new values. Before your component is removed from the DOM, React will run your cleanup function. +* `setup`: The function with your Effect's logic. Your setup function may also optionally return a *cleanup* function. When your component is added to the DOM, but before any layout effects fire, React will run your setup function. After every re-render with changed dependencies, React will first run the cleanup function (if you provided it) with the old values, and then run your setup function with the new values. When your component is removed from the DOM, React will run your cleanup function. * **optional** `dependencies`: The list of all reactive values referenced inside of the `setup` code. Reactive values include props, state, and all the variables and functions declared directly inside your component body. If your linter is [configured for React](/learn/editor-setup#linting), it will verify that every reactive value is correctly specified as a dependency. The list of dependencies must have a constant number of items and be written inline like `[dep1, dep2, dep3]`. React will compare each dependency with its previous value using the [`Object.is`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/is) comparison algorithm. If you don't specify the dependencies at all, your Effect will re-run after every re-render of the component. @@ -56,8 +56,9 @@ function useCSS(rule) { * Effects only run on the client. They don't run during server rendering. * You can't update state from inside `useInsertionEffect`. -* By the time `useInsertionEffect` runs, refs are not attached yet, and DOM is not yet updated. - +* By the time `useInsertionEffect` runs, refs are not attached yet. +* `useInsertionEffect` may run either before or after the DOM has been updated. You shouldn't rely on the DOM being updated at any particular time. +* Unlike other types of Effects, which fire cleanup for every Effect and then setup for every Effect, `useInsertionEffect` will fire both cleanup and setup one component at a time. This results in an "interleaving" of the cleanup and setup functions. --- ## Usage {/*usage*/} @@ -87,7 +88,7 @@ If you use CSS-in-JS, we recommend a combination of the first two approaches (CS The first problem is not solvable, but `useInsertionEffect` helps you solve the second problem. -Call `useInsertionEffect` to insert the styles before any DOM mutations: +Call `useInsertionEffect` to insert the styles before any layout effects fire: ```js {4-11} // Inside your CSS-in-JS library From cf4ad1999a766f417bee506f11b37a6d05ac9342 Mon Sep 17 00:00:00 2001 From: Soichiro Miki Date: Tue, 25 Jul 2023 09:57:55 +0900 Subject: [PATCH 004/106] Fix typo: "server-only" to "client-only" (#6164) --- src/content/reference/react/Suspense.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/content/reference/react/Suspense.md b/src/content/reference/react/Suspense.md index 27add6035..dd9312055 100644 --- a/src/content/reference/react/Suspense.md +++ b/src/content/reference/react/Suspense.md @@ -2513,7 +2513,7 @@ However, now imagine you're navigating between two different user profiles. In t --- -### Providing a fallback for server errors and server-only content {/*providing-a-fallback-for-server-errors-and-server-only-content*/} +### Providing a fallback for server errors and client-only content {/*providing-a-fallback-for-server-errors-and-client-only-content*/} If you use one of the [streaming server rendering APIs](/reference/react-dom/server) (or a framework that relies on them), React will also use your `` boundaries to handle errors on the server. If a component throws an error on the server, React will not abort the server render. Instead, it will find the closest `` component above it and include its fallback (such as a spinner) into the generated server HTML. The user will see a spinner at first. From a132d8f35597d0380f0f738c1b095b5dc56736ba Mon Sep 17 00:00:00 2001 From: Soichiro Miki Date: Tue, 25 Jul 2023 09:59:14 +0900 Subject: [PATCH 005/106] Remove junk lines in common.md (#6167) --- src/content/reference/react-dom/components/common.md | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/content/reference/react-dom/components/common.md b/src/content/reference/react-dom/components/common.md index f1e4fcd0c..fb0078906 100644 --- a/src/content/reference/react-dom/components/common.md +++ b/src/content/reference/react-dom/components/common.md @@ -149,7 +149,6 @@ These standard DOM props are also supported for all built-in components: * [`onWheel`](https://developer.mozilla.org/en-US/docs/Web/API/Element/wheel_event): A [`WheelEvent` handler](#wheelevent-handler) function. Fires when the user rotates a wheel button. * `onWheelCapture`: A version of `onWheel` that fires in the [capture phase.](/learn/responding-to-events#capture-phase-events) * [`role`](https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Roles): A string. Specifies the element role explicitly for assistive technologies. -nt. * [`slot`](https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Roles): A string. Specifies the slot name when using shadow DOM. In React, an equivalent pattern is typically achieved by passing JSX as props, for example `} right={} />`. * [`spellCheck`](https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/spellcheck): A boolean or null. If explicitly set to `true` or `false`, enables or disables spellchecking. * [`tabIndex`](https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/tabindex): A number. Overrides the default Tab button behavior. [Avoid using values other than `-1` and `0`.](https://www.tpgi.com/using-the-tabindex-attribute/) @@ -169,7 +168,6 @@ These events fire only for the [``](https://developer.mozilla.org/en-US/ * [`onCancel`](https://developer.mozilla.org/en-US/docs/Web/API/HTMLDialogElement/cancel_event): An [`Event` handler](#event-handler) function. Fires when the user tries to dismiss the dialog. * `onCancelCapture`: A version of `onCancel` that fires in the [capture phase.](/learn/responding-to-events#capture-phase-events) -capture-phase-events) * [`onClose`](https://developer.mozilla.org/en-US/docs/Web/API/HTMLDialogElement/close_event): An [`Event` handler](#event-handler) function. Fires when a dialog has been closed. * `onCloseCapture`: A version of `onClose` that fires in the [capture phase.](/learn/responding-to-events#capture-phase-events) @@ -177,7 +175,6 @@ These events fire only for the [`
`](https://developer.mozilla.org/en-US * [`onToggle`](https://developer.mozilla.org/en-US/docs/Web/API/HTMLDetailsElement/toggle_event): An [`Event` handler](#event-handler) function. Fires when the user toggles the details. * `onToggleCapture`: A version of `onToggle` that fires in the [capture phase.](/learn/responding-to-events#capture-phase-events) -capture-phase-events) These events fire for [``](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/img), [`