refactor(theme): move LayoutProviders to Layout/Provider; composeProviders util (#7676)

Co-authored-by: Joshua Chen <sidachen2003@gmail.com>
This commit is contained in:
Sébastien Lorber 2022-06-24 18:36:27 +02:00 committed by GitHub
parent 90a8ca387e
commit afc08eef4f
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
7 changed files with 79 additions and 44 deletions

View file

@ -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 {

View file

@ -40,6 +40,7 @@ export {
useIsomorphicLayoutEffect,
useEvent,
usePrevious,
composeProviders,
ReactContextError,
} from './utils/reactUtils';

View file

@ -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,
)}
</>
);
}