mirror of
https://github.com/facebook/docusaurus.git
synced 2025-05-22 13:37:05 +02:00
refactor(theme): move LayoutProviders to Layout/Provider; composeProviders util (#7676)
Co-authored-by: Joshua Chen <sidachen2003@gmail.com>
This commit is contained in:
parent
90a8ca387e
commit
afc08eef4f
7 changed files with 79 additions and 44 deletions
|
@ -596,14 +596,14 @@ declare module '@theme/Layout' {
|
|||
export default function Layout(props: Props): JSX.Element;
|
||||
}
|
||||
|
||||
declare module '@theme/LayoutProviders' {
|
||||
declare module '@theme/Layout/Provider' {
|
||||
import type {ReactNode} from 'react';
|
||||
|
||||
export interface Props {
|
||||
readonly children: ReactNode;
|
||||
}
|
||||
|
||||
export default function LayoutProviders(props: Props): JSX.Element;
|
||||
export default function LayoutProvider(props: Props): JSX.Element;
|
||||
}
|
||||
|
||||
declare module '@theme/SearchMetadata' {
|
||||
|
|
|
@ -0,0 +1,33 @@
|
|||
/**
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
import React from 'react';
|
||||
import {composeProviders} from '@docusaurus/theme-common';
|
||||
import {
|
||||
ColorModeProvider,
|
||||
TabGroupChoiceProvider,
|
||||
AnnouncementBarProvider,
|
||||
DocsPreferredVersionContextProvider,
|
||||
ScrollControllerProvider,
|
||||
NavbarProvider,
|
||||
PluginHtmlClassNameProvider,
|
||||
} from '@docusaurus/theme-common/internal';
|
||||
import type {Props} from '@theme/Layout/Provider';
|
||||
|
||||
const Provider = composeProviders([
|
||||
ColorModeProvider,
|
||||
AnnouncementBarProvider,
|
||||
TabGroupChoiceProvider,
|
||||
ScrollControllerProvider,
|
||||
DocsPreferredVersionContextProvider,
|
||||
PluginHtmlClassNameProvider,
|
||||
NavbarProvider,
|
||||
]);
|
||||
|
||||
export default function LayoutProvider({children}: Props): JSX.Element {
|
||||
return <Provider>{children}</Provider>;
|
||||
}
|
|
@ -14,7 +14,7 @@ import SkipToContent from '@theme/SkipToContent';
|
|||
import AnnouncementBar from '@theme/AnnouncementBar';
|
||||
import Navbar from '@theme/Navbar';
|
||||
import Footer from '@theme/Footer';
|
||||
import LayoutProviders from '@theme/LayoutProviders';
|
||||
import LayoutProvider from '@theme/Layout/Provider';
|
||||
import ErrorPageContent from '@theme/ErrorPageContent';
|
||||
import type {Props} from '@theme/Layout';
|
||||
import styles from './styles.module.css';
|
||||
|
@ -32,7 +32,7 @@ export default function Layout(props: Props): JSX.Element {
|
|||
useKeyboardNavigation();
|
||||
|
||||
return (
|
||||
<LayoutProviders>
|
||||
<LayoutProvider>
|
||||
<PageMetadata title={title} description={description} />
|
||||
|
||||
<SkipToContent />
|
||||
|
@ -53,6 +53,6 @@ export default function Layout(props: Props): JSX.Element {
|
|||
</div>
|
||||
|
||||
{!noFooter && <Footer />}
|
||||
</LayoutProviders>
|
||||
</LayoutProvider>
|
||||
);
|
||||
}
|
||||
|
|
|
@ -1,36 +0,0 @@
|
|||
/**
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
import React from 'react';
|
||||
import {
|
||||
ColorModeProvider,
|
||||
TabGroupChoiceProvider,
|
||||
AnnouncementBarProvider,
|
||||
DocsPreferredVersionContextProvider,
|
||||
ScrollControllerProvider,
|
||||
NavbarProvider,
|
||||
PluginHtmlClassNameProvider,
|
||||
} from '@docusaurus/theme-common/internal';
|
||||
import type {Props} from '@theme/LayoutProviders';
|
||||
|
||||
export default function LayoutProviders({children}: Props): JSX.Element {
|
||||
return (
|
||||
<ColorModeProvider>
|
||||
<AnnouncementBarProvider>
|
||||
<TabGroupChoiceProvider>
|
||||
<ScrollControllerProvider>
|
||||
<DocsPreferredVersionContextProvider>
|
||||
<PluginHtmlClassNameProvider>
|
||||
<NavbarProvider>{children}</NavbarProvider>
|
||||
</PluginHtmlClassNameProvider>
|
||||
</DocsPreferredVersionContextProvider>
|
||||
</ScrollControllerProvider>
|
||||
</TabGroupChoiceProvider>
|
||||
</AnnouncementBarProvider>
|
||||
</ColorModeProvider>
|
||||
);
|
||||
}
|
|
@ -175,7 +175,7 @@ function DocsPreferredVersionContextProviderUnsafe({
|
|||
export function DocsPreferredVersionContextProvider({
|
||||
children,
|
||||
}: {
|
||||
children: JSX.Element;
|
||||
children: ReactNode;
|
||||
}): JSX.Element {
|
||||
if (isDocsPluginEnabled) {
|
||||
return (
|
||||
|
@ -184,7 +184,7 @@ export function DocsPreferredVersionContextProvider({
|
|||
</DocsPreferredVersionContextProviderUnsafe>
|
||||
);
|
||||
}
|
||||
return children;
|
||||
return <>{children}</>;
|
||||
}
|
||||
|
||||
function useDocsPreferredVersionContext(): ContextValue {
|
||||
|
|
|
@ -40,6 +40,7 @@ export {
|
|||
useIsomorphicLayoutEffect,
|
||||
useEvent,
|
||||
usePrevious,
|
||||
composeProviders,
|
||||
ReactContextError,
|
||||
} from './utils/reactUtils';
|
||||
|
||||
|
|
|
@ -5,7 +5,15 @@
|
|||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
import {useCallback, useEffect, useLayoutEffect, useMemo, useRef} from 'react';
|
||||
import React, {
|
||||
useCallback,
|
||||
useEffect,
|
||||
useLayoutEffect,
|
||||
useMemo,
|
||||
useRef,
|
||||
type ComponentType,
|
||||
type ReactNode,
|
||||
} from 'react';
|
||||
import ExecutionEnvironment from '@docusaurus/ExecutionEnvironment';
|
||||
|
||||
/**
|
||||
|
@ -90,3 +98,32 @@ export function useShallowMemoObject<O extends object>(obj: O): O {
|
|||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
return useMemo(() => obj, deps.flat());
|
||||
}
|
||||
|
||||
type SimpleProvider = ComponentType<{children: ReactNode}>;
|
||||
|
||||
/**
|
||||
* Creates a single React provider from an array of existing providers
|
||||
* assuming providers only take "children" as props.
|
||||
*
|
||||
* Prevents the annoying React element nesting
|
||||
* Example here: https://getfrontend.tips/compose-multiple-react-providers/
|
||||
*
|
||||
* The order matters:
|
||||
* - The first provider is at the top of the tree.
|
||||
* - The last provider is the most nested one
|
||||
*
|
||||
* @param providers array of providers to compose
|
||||
*/
|
||||
export function composeProviders(providers: SimpleProvider[]): SimpleProvider {
|
||||
// Creates a single React component: it's cheaper to compose JSX elements
|
||||
return ({children}) => (
|
||||
<>
|
||||
{providers.reduceRight(
|
||||
(element, CurrentProvider) => (
|
||||
<CurrentProvider>{element}</CurrentProvider>
|
||||
),
|
||||
children,
|
||||
)}
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue