Browse Source

[Beta] Autogen API table of contents (#4995)

main
dan 2 years ago
committed by GitHub
parent
commit
a73274f094
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 5
      beta/src/components/Layout/MarkdownPage.tsx
  2. 7
      beta/src/components/Layout/Toc.tsx
  3. 53
      beta/src/components/MDX/MDXComponents.tsx
  4. 15
      beta/src/components/MDX/TocContext.tsx
  5. 14
      beta/src/content/apis/react-dom/client/createRoot.md
  6. 8
      beta/src/content/apis/react-dom/client/hydrateRoot.md
  7. 2
      beta/src/content/apis/react-dom/createPortal.md
  8. 2
      beta/src/content/apis/react-dom/findDOMNode.md
  9. 2
      beta/src/content/apis/react-dom/flushSync.md
  10. 9
      beta/src/content/apis/react-dom/hydrate.md
  11. 9
      beta/src/content/apis/react-dom/render.md
  12. 2
      beta/src/content/apis/react-dom/server/renderToNodeStream.md
  13. 2
      beta/src/content/apis/react-dom/server/renderToPipeableStream.md
  14. 2
      beta/src/content/apis/react-dom/server/renderToReadableStream.md
  15. 2
      beta/src/content/apis/react-dom/server/renderToStaticMarkup.md
  16. 2
      beta/src/content/apis/react-dom/server/renderToStaticNodeStream.md
  17. 2
      beta/src/content/apis/react-dom/server/renderToString.md
  18. 2
      beta/src/content/apis/react-dom/unmountComponentAtNode.md
  19. 2
      beta/src/content/apis/react/Children.md
  20. 2
      beta/src/content/apis/react/Component.md
  21. 8
      beta/src/content/apis/react/Fragment.md
  22. 2
      beta/src/content/apis/react/PureComponent.md
  23. 1
      beta/src/content/apis/react/StrictMode.md
  24. 2
      beta/src/content/apis/react/Suspense.md
  25. 2
      beta/src/content/apis/react/cloneElement.md
  26. 10
      beta/src/content/apis/react/createContext.md
  27. 2
      beta/src/content/apis/react/createElement.md
  28. 2
      beta/src/content/apis/react/createFactory.md
  29. 2
      beta/src/content/apis/react/createRef.md
  30. 2
      beta/src/content/apis/react/forwardRef.md
  31. 2
      beta/src/content/apis/react/isValidElement.md
  32. 2
      beta/src/content/apis/react/lazy.md
  33. 2
      beta/src/content/apis/react/memo.md
  34. 2
      beta/src/content/apis/react/startTransition.md
  35. 2
      beta/src/content/apis/react/useCallback.md
  36. 12
      beta/src/content/apis/react/useContext.md
  37. 2
      beta/src/content/apis/react/useDebugValue.md
  38. 2
      beta/src/content/apis/react/useDeferredValue.md
  39. 2
      beta/src/content/apis/react/useEffect.md
  40. 2
      beta/src/content/apis/react/useId.md
  41. 2
      beta/src/content/apis/react/useImperativeHandle.md
  42. 2
      beta/src/content/apis/react/useInsertionEffect.md
  43. 2
      beta/src/content/apis/react/useLayoutEffect.md
  44. 2
      beta/src/content/apis/react/useMemo.md
  45. 15
      beta/src/content/apis/react/useReducer.md
  46. 9
      beta/src/content/apis/react/useRef.md
  47. 17
      beta/src/content/apis/react/useState.md
  48. 2
      beta/src/content/apis/react/useSyncExternalStore.md
  49. 2
      beta/src/content/apis/react/useTransition.md
  50. 8
      beta/src/utils/prepareMDX.js

5
beta/src/components/Layout/MarkdownPage.tsx

@ -8,6 +8,7 @@ import {MDXComponents} from 'components/MDX/MDXComponents';
import {Seo} from 'components/Seo';
import PageHeading from 'components/PageHeading';
import {useRouteMeta} from './useRouteMeta';
import {TocContext} from '../MDX/TocContext';
import {Toc} from './Toc';
export interface MarkdownProps<Frontmatter> {
@ -43,7 +44,9 @@ export function MarkdownPage<
/>
)}
<div className="px-5 sm:px-12">
<div className="max-w-7xl mx-auto">{children}</div>
<div className="max-w-7xl mx-auto">
<TocContext.Provider value={toc}>{children}</TocContext.Provider>
</div>
<DocsPageFooter
route={route}
nextRoute={nextRoute}

7
beta/src/components/Layout/Toc.tsx

@ -5,12 +5,9 @@
import cx from 'classnames';
import * as React from 'react';
import {useTocHighlight} from './useTocHighlight';
import type {Toc} from '../MDX/TocContext';
export function Toc({
headings,
}: {
headings: Array<{url: string; text: React.ReactNode; depth: number}>;
}) {
export function Toc({headings}: {headings: Toc}) {
const {currentIndex} = useTocHighlight();
// TODO: We currently have a mismatch between the headings in the document
// and the headings we find in MarkdownPage (i.e. we don't find Recap or Challenges).

53
beta/src/components/MDX/MDXComponents.tsx

@ -27,6 +27,8 @@ import YouWillLearnCard from './YouWillLearnCard';
import {Challenges, Hint, Solution} from './Challenges';
import {IconNavArrow} from '../Icon/IconNavArrow';
import ButtonLink from 'components/ButtonLink';
import {TocContext} from './TocContext';
import type {Toc, TocItem} from './TocContext';
function CodeStep({children, step}: {children: any; step: number}) {
return (
@ -270,6 +272,56 @@ function IllustrationBlock({
);
}
type NestedTocRoot = {
item: null;
children: Array<NestedTocNode>;
};
type NestedTocNode = {
item: TocItem;
children: Array<NestedTocNode>;
};
function calculateNestedToc(toc: Toc): NestedTocRoot {
const currentAncestors = new Map<number, NestedTocNode | NestedTocRoot>();
const root: NestedTocRoot = {
item: null,
children: [],
};
const startIndex = 1; // Skip "Overview"
for (let i = startIndex; i < toc.length; i++) {
const item = toc[i];
const currentParent: NestedTocNode | NestedTocRoot =
currentAncestors.get(item.depth - 1) || root;
const node: NestedTocNode = {
item,
children: [],
};
currentParent.children.push(node);
currentAncestors.set(item.depth, node);
}
return root;
}
function InlineToc() {
const toc = React.useContext(TocContext);
const root = React.useMemo(() => calculateNestedToc(toc), [toc]);
return <InlineTocItem items={root.children} />;
}
function InlineTocItem({items}: {items: Array<NestedTocNode>}) {
return (
<UL>
{items.map((node) => (
<LI key={node.item.url}>
<Link href={node.item.url}>{node.item.text}</Link>
{node.children.length > 0 && <InlineTocItem items={node.children} />}
</LI>
))}
</UL>
);
}
export const MDXComponents = {
p: P,
strong: Strong,
@ -309,6 +361,7 @@ export const MDXComponents = {
Illustration,
IllustrationBlock,
Intro,
InlineToc,
LearnMore,
Math,
MathI,

15
beta/src/components/MDX/TocContext.tsx

@ -0,0 +1,15 @@
/*
* Copyright (c) Facebook, Inc. and its affiliates.
*/
import {createContext} from 'react';
import type {ReactNode} from 'react';
export type TocItem = {
url: string;
text: ReactNode;
depth: number;
};
export type Toc = Array<TocItem>;
export const TocContext = createContext<Toc>([]);

14
beta/src/content/apis/react-dom/client/createRoot.md

@ -12,19 +12,7 @@ const root = createRoot(domNode, options?)
</Intro>
- [Usage](#usage)
- [Rendering an app fully built with React](#rendering-an-app-fully-built-with-react)
- [Rendering a page partially built with React](#rendering-a-page-partially-built-with-react)
- [Updating a root component](#updating-a-root-component)
- [Reference](#reference)
- [`createRoot(domNode, options?)`](#create-root)
- [`root.render(reactNode)`](#root-render)
- [`root.unmount()`](#root-unmount)
- [Troubleshooting](#troubleshooting)
- [I've created a root, but nothing is displayed](#ive-created-a-root-but-nothing-is-displayed)
- [I'm getting an error: "Target container is not a DOM element"](#im-getting-an-error-target-container-is-not-a-dom-element)
- [I'm getting an error: "Functions are not valid as a React child."](#im-getting-an-error-functions-are-not-valid-as-a-react-child)
- [My server-rendered HTML gets re-created from scratch](#my-server-rendered-html-gets-re-created-from-scratch)
<InlineToc />
---

8
beta/src/content/apis/react-dom/client/hydrateRoot.md

@ -12,13 +12,7 @@ const root = hydrateRoot(domNode, reactNode, options?)
</Intro>
- [Usage](#usage)
- [Hydrating server-rendered HTML](#hydrating-server-rendered-html)
- [Updating a hydrated root component](#updating-a-hydrated-root-component)
- [Reference](#reference)
- [`hydrateRoot(domNode, reactNode, options?)`](#hydrate-root)
- [`root.render(reactNode)`](#root-render)
- [`root.unmount()`](#root-unmount)
<InlineToc />
---

2
beta/src/content/apis/react-dom/createPortal.md

@ -19,3 +19,5 @@ createPortal(child, container)
```
</Intro>
<InlineToc />

2
beta/src/content/apis/react-dom/findDOMNode.md

@ -19,6 +19,8 @@ findDOMNode(component)
</Intro>
<InlineToc />
<Gotcha>
`findDOMNode` is an escape hatch used to access the underlying DOM node. In most cases, use of this escape hatch is discouraged because it pierces the component abstraction. [It has been deprecated in StrictMode](https://reactjs.org/docs/strict-mode.html#warning-about-deprecated-finddomnode-usage).

2
beta/src/content/apis/react-dom/flushSync.md

@ -19,3 +19,5 @@ flushSync(callback)
```
</Intro>
<InlineToc />

9
beta/src/content/apis/react-dom/hydrate.md

@ -17,14 +17,7 @@ hydrate(reactNode, domNode, callback?)
</Intro>
- [Usage](#usage)
- [Hydrating server-rendered HTML](#hydrating-server-rendered-html)
- [Unavoidable hydration mismatches](#avoiding-unavoidable-hydration-mismatches)
- [Handling different client and server content](#handling-different-client-and-server-content)
- [Reference](#reference)
- [`hydrateRoot(domNode, reactNode, callback?)`](#hydrate-root)
- [`root.render(reactNode)`](#render-root)
- [`root.unmount()`](#unmount-root)
<InlineToc />
---

9
beta/src/content/apis/react-dom/render.md

@ -19,14 +19,7 @@ render(reactNode, domNode, callback?)
</Intro>
- [Usage](#usage)
- [Rendering the root component](#rendering-the-root-component)
- [Rendering multiple roots](#rendering-multiple-roots)
- [Updating the rendered tree](#updating-the-rendered-tree)
- [Reference](#reference)
- [`render(reactNode, domNode, callback?)`](#render)
<InlineToc />
---

2
beta/src/content/apis/react-dom/server/renderToNodeStream.md

@ -19,3 +19,5 @@ renderToNodeStream(element)
```
</Intro>
<InlineToc />

2
beta/src/content/apis/react-dom/server/renderToPipeableStream.md

@ -19,3 +19,5 @@ renderToPipeableStream(element, options)
```
</Intro>
<InlineToc />

2
beta/src/content/apis/react-dom/server/renderToReadableStream.md

@ -19,3 +19,5 @@ renderToReadableStream(element, options);
```
</Intro>
<InlineToc />

2
beta/src/content/apis/react-dom/server/renderToStaticMarkup.md

@ -21,3 +21,5 @@ renderToStaticMarkup(element)
If you plan to use React on the client to make the markup interactive, do not use this method. Instead, use renderToString on the server and ReactDOM.hydrateRoot() on the client.
</Intro>
<InlineToc />

2
beta/src/content/apis/react-dom/server/renderToStaticNodeStream.md

@ -19,3 +19,5 @@ renderToStaticNodeStream(element)
```
</Intro>
<InlineToc />

2
beta/src/content/apis/react-dom/server/renderToString.md

@ -19,3 +19,5 @@ renderToString(element)
```
</Intro>
<InlineToc />

2
beta/src/content/apis/react-dom/unmountComponentAtNode.md

@ -18,3 +18,5 @@ unmountComponentAtNode(container)
```
</Intro>
<InlineToc />

2
beta/src/content/apis/react/Children.md

@ -16,3 +16,5 @@ This section is incomplete, please see the old docs for [React.Children](https:/
See the [React.Children](https://reactjs.org/docs/react-api.html#reactchildren) docs for more info.
</Intro>
<InlineToc />

2
beta/src/content/apis/react/Component.md

@ -24,3 +24,5 @@ class Welcome extends React.Component {
The only method you must define in a `React.Component` subclass is called `render()`. All the other methods described on are optional. Please see the old [React.Component](https://reactjs.org/docs/react-component.html) docs for more info.
</Intro>
<InlineToc />

8
beta/src/content/apis/react/Fragment.md

@ -21,13 +21,7 @@ function Component() {
</Intro>
- [Usage](#usage)
- [Returning multiple elements](#returning-multiple-elements)
- [Assigning multiple elements to a variable](#assigning-multiple-elements-to-a-variable)
- [Grouping elements with text](#grouping-elements-with-text)
- [Rendering a list of Fragments](#rendering-a-list-of-fragments)
- [Reference](#reference)
- [React.Fragment](#react-fragment)
<InlineToc />
---

2
beta/src/content/apis/react/PureComponent.md

@ -24,3 +24,5 @@ class Welcome extends React.PureComponent {
```
</Intro>
<InlineToc />

1
beta/src/content/apis/react/StrictMode.md

@ -8,3 +8,4 @@ This section is incomplete, please see the old docs for [StrictMode](https://rea
</Wip>
<InlineToc />

2
beta/src/content/apis/react/Suspense.md

@ -16,3 +16,5 @@ This section is incomplete, please see the old docs for [Suspense](https://react
```
</Intro>
<InlineToc />

2
beta/src/content/apis/react/cloneElement.md

@ -16,3 +16,5 @@ React.cloneElement(element, [config], [...children])
```
</Intro>
<InlineToc />

10
beta/src/content/apis/react/createContext.md

@ -12,15 +12,7 @@ const SomeContext = createContext(defaultValue)
</Intro>
- [Usage](#usage)
- [Creating context](#creating-context)
- [Importing and exporting context from a file](#importing-and-exporting-context-from-a-file)
- [Reference](#reference)
- [`createContext(defaultValue)`](#createcontext)
- [`SomeContext.Provider`](#provider)
- [`SomeContext.Consumer`](#consumer)
- [Troubleshooting](#troubleshooting)
- [I can't find a way to change the context value](#troubleshooting)
<InlineToc />
---

2
beta/src/content/apis/react/createElement.md

@ -16,3 +16,5 @@ React.createElement(type, [props], [...children])
```
</Intro>
<InlineToc />

2
beta/src/content/apis/react/createFactory.md

@ -16,3 +16,5 @@ React.createFactory(type)
```
</Intro>
<InlineToc />

2
beta/src/content/apis/react/createRef.md

@ -16,3 +16,5 @@ React.createRef();
```
</Intro>
<InlineToc />

2
beta/src/content/apis/react/forwardRef.md

@ -22,3 +22,5 @@ const FancyButton = React.forwardRef((props, ref) => (
```
</Intro>
<InlineToc />

2
beta/src/content/apis/react/isValidElement.md

@ -18,3 +18,5 @@ React.isValidElement(object)
```
</Intro>
<InlineToc />

2
beta/src/content/apis/react/lazy.md

@ -19,3 +19,5 @@ const SomeComponent = React.lazy(() => import('./SomeComponent'));
```
</Intro>
<InlineToc />

2
beta/src/content/apis/react/memo.md

@ -18,3 +18,5 @@ const MyComponent = React.memo(function MyComponent(props) {
```
</Intro>
<InlineToc />

2
beta/src/content/apis/react/startTransition.md

@ -16,3 +16,5 @@ React.startTransition(callback);
```
</Intro>
<InlineToc />

2
beta/src/content/apis/react/useCallback.md

@ -16,3 +16,5 @@ const memoizedCallback = useCallback(callback, [...dependencies])
```
</Intro>
<InlineToc />

12
beta/src/content/apis/react/useContext.md

@ -12,17 +12,7 @@ const value = useContext(SomeContext)
</Intro>
- [Usage](#usage)
- [Passing data deeply into the tree](#passing-data-deeply-into-the-tree)
- [Updating data passed via context](#updating-data-passed-via-context)
- [Specifying a fallback default value](#specifying-a-fallback-default-value)
- [Overriding context for a part of the tree](#overriding-context-for-a-part-of-the-tree)
- [Optimizing re-renders when passing objects and functions](#optimizing-re-renders-when-passing-objects-and-functions)
- [Reference](#reference)
- [`useContext(SomeContext)`](#usecontext)
- [Troubleshooting](#troubleshooting)
- [My component doesn't see the value from my provider](#my-component-doesnt-see-the-value-from-my-provider)
- [I am always getting undefined from my context although the default value is different](#i-am-always-getting-undefined-from-my-context-although-the-default-value-is-different)
<InlineToc />
---

2
beta/src/content/apis/react/useDebugValue.md

@ -18,3 +18,5 @@ useDebugValue(value)
```
</Intro>
<InlineToc />

2
beta/src/content/apis/react/useDeferredValue.md

@ -18,3 +18,5 @@ const deferredValue = useDeferredValue(value);
```
</Intro>
<InlineToc />

2
beta/src/content/apis/react/useEffect.md

@ -16,3 +16,5 @@ useEffect(callback, [...dependencies])
```
</Intro>
<InlineToc />

2
beta/src/content/apis/react/useId.md

@ -19,6 +19,8 @@ const id = useId();
</Intro>
<InlineToc />
<Gotcha>
`useId` is not for generating keys in a list. Keys should be generated from your data.

2
beta/src/content/apis/react/useImperativeHandle.md

@ -16,3 +16,5 @@ useImperativeHandle(ref, createHandle, [deps])
```
</Intro>
<InlineToc />

2
beta/src/content/apis/react/useInsertionEffect.md

@ -19,6 +19,8 @@ useInsertionEffect(didUpdate);
</Intro>
<InlineToc />
<Gotcha>
`useInsertionEffect` should be limited to css-in-js library authors. Prefer [`useEffect`](/apis/react/useEffect) or [`useLayoutEffect`](/apis/react/useLayoutEffect) instead.

2
beta/src/content/apis/react/useLayoutEffect.md

@ -16,3 +16,5 @@ useLayoutEffect(callback, [...dependencies])
```
</Intro>
<InlineToc />

2
beta/src/content/apis/react/useMemo.md

@ -16,3 +16,5 @@ const memoizedValue = useMemo(callback, [...dependencies])
```
</Intro>
<InlineToc />

15
beta/src/content/apis/react/useReducer.md

@ -12,20 +12,7 @@ const [state, dispatch] = useReducer(reducer, initialArg, init)
</Intro>
- [Usage](#usage)
- [Adding a reducer to a component](#adding-a-reducer-to-a-component)
- [Writing the reducer function](#writing-the-reducer-function)
- [Avoiding recreating the initial state](#avoiding-recreating-the-initial-state)
- [Reference](#reference)
- [`useReducer(reducer, initialArg, init?)`](#usereducer)
- [`dispatch` functions](#dispatch)
- [Troubleshooting](#troubleshooting)
- [I've dispatched an action, but logging gives me the old state value](#ive-dispatched-an-action-but-logging-gives-me-the-old-state-value)
- [I've dispatched an action, but the screen doesn't update](#ive-dispatched-an-action-but-the-screen-doesnt-update)
- [A part of my reducer state becomes undefined after dispatching](#a-part-of-my-reducer-state-becomes-undefined-after-dispatching)
- [My entire reducer state becomes undefined after dispatching](#my-entire-reducer-state-becomes-undefined-after-dispatching)
- [I'm getting an error: "Too many re-renders"](#im-getting-an-error-too-many-re-renders)
- [My reducer or initializer function runs twice](#my-reducer-or-initializer-function-runs-twice)
<InlineToc />
---

9
beta/src/content/apis/react/useRef.md

@ -12,14 +12,7 @@ const ref = useRef(initialValue)
</Intro>
- [Usage](#usage)
- [Referencing a value with a ref](#referencing-a-value-with-a-ref)
- [Manipulating the DOM with a ref](#manipulating-the-dom-with-a-ref)
- [Avoiding recreating the ref contents](#avoiding-recreating-the-ref-contents)
- [Reference](#reference)
- [`useRef(initialValue)`](#useref)
- [Troubleshooting](#troubleshooting)
- [I can’t get a ref to a custom component](#i-cant-get-a-ref-to-a-custom-component)
<InlineToc />
---

17
beta/src/content/apis/react/useState.md

@ -12,22 +12,7 @@ const [state, setState] = useState(initialState)
</Intro>
- [Usage](#usage)
- [Adding state to a component](#adding-state-to-a-component)
- [Updating state based on the previous state](#updating-state-based-on-the-previous-state)
- [Updating objects and arrays in state](#updating-objects-and-arrays-in-state)
- [Avoiding recreating the initial state](#avoiding-recreating-the-initial-state)
- [Resetting state with a key](#resetting-state-with-a-key)
- [Storing information from previous renders](#storing-information-from-previous-renders)
- [Reference](#reference)
- [`useState(initialState)`](#usestate)
- [`set` functions, like `setSomething(nextState)`](#setstate)
- [Troubleshooting](#troubleshooting)
- [I’ve updated the state, but logging gives me the old value](#ive-updated-the-state-but-logging-gives-me-the-old-value)
- [I've updated the state, but the screen doesn't update](#ive-updated-the-state-but-the-screen-doesnt-update)
- [I'm getting an error: "Too many re-renders"](#im-getting-an-error-too-many-re-renders)
- [My initializer or updater function runs twice](#my-initializer-or-updater-function-runs-twice)
- [I'm trying to set state to a function, but it gets called instead](#im-trying-to-set-state-to-a-function-but-it-gets-called-instead)
<InlineToc />
---

2
beta/src/content/apis/react/useSyncExternalStore.md

@ -18,3 +18,5 @@ const state = useSyncExternalStore(subscribe, getSnapshot, getServerSnapshot?);
```
</Intro>
<InlineToc />

2
beta/src/content/apis/react/useTransition.md

@ -16,3 +16,5 @@ const [isPending, startTransition] = useTransition();
```
</Intro>
<InlineToc />

8
beta/src/utils/prepareMDX.js

@ -69,14 +69,14 @@ function getTableOfContents(children) {
if (child.type === 'Challenges') {
return {
url: '#challenges',
depth: 0,
depth: 2,
text: 'Challenges',
};
}
if (child.type === 'Recap') {
return {
url: '#recap',
depth: 0,
depth: 2,
text: 'Recap',
};
}
@ -88,9 +88,9 @@ function getTableOfContents(children) {
});
if (anchors.length > 0) {
anchors.unshift({
depth: 1,
text: 'Overview',
url: '#',
text: 'Overview',
depth: 2,
});
}
return anchors;

Loading…
Cancel
Save