@plone/providers
This package contains utility providers for Plone React components.
The main purpose is to provide dependency injection of common required artifacts needed by any app.
These artifacts include:
- Router related
- Plone Client
- URL handling methods
[!WARNING]
This package or app is experimental.
The community offers no support whatsoever for it.
Breaking changes may occur without notice.
PloneProvider
It provides all the necessary artifacts that an app can need grouped in a single provider.
interface PloneProvider {
ploneClient: InstanceType<typeof PloneClient>;
queryClient: QueryClient;
useLocation: () => Location | undefined;
useParams: (opts?: any) => Record<string, string>;
navigate: (path: string) => void;
useHref: (to: string, options?: any) => string;
flattenToAppURL: (path: string | undefined) => string | undefined;
}
It should be instantiated at the top of your app.
You have to provide the required props depending on the framework and the router used.
This is the example for a Next.js app.
Please refer to the {file}apps
folder of the Volto repository for more examples of the usage of PloneProvider
in different React frameworks.
'use client';
import React from 'react';
import {
useRouter,
usePathname,
useSearchParams,
useParams,
} from 'next/navigation';
import { QueryClient } from '@tanstack/react-query';
import { PloneProvider } from '@plone/providers';
import PloneClient from '@plone/client';
import { ReactQueryDevtools } from '@tanstack/react-query-devtools';
import { flattenToAppURL } from './utils';
import config from './config';
function useLocation() {
let pathname = usePathname();
let search = useSearchParams();
return {
pathname,
search,
searchStr: '',
hash: (typeof window !== 'undefined' && window.location.hash) || '',
href: (typeof window !== 'undefined' && window.location.href) || '',
};
}
const Providers: React.FC<{
children?: React.ReactNode;
}> = ({ children }) => {
const [queryClient] = React.useState(
() =>
new QueryClient({
defaultOptions: {
queries: {
staleTime: 60 * 1000,
},
},
}),
);
const [ploneClient] = React.useState(() =>
PloneClient.initialize({
apiPath: config.settings.apiPath,
}),
);
const router = useRouter();
return (
<PloneProvider
ploneClient={ploneClient}
queryClient={queryClient}
// NextJS doesn't have a useLocation hook, so we need to unify this
// in a custom hook
useLocation={useLocation}
navigate={(to) => {
router.push(to);
}}
useParams={useParams}
useHref={(to) => flattenToAppURL(to)}
flattenToAppURL={flattenToAppURL}
>
{children}
<ReactQueryDevtools initialIsOpen={false} />
</PloneProvider>
);
};
export default Providers;
You can use it anywhere in your app by using the hook usePloneProvider
.
import { usePloneProvider } from '@plone/providers';
const { ploneClient } = usePloneProvider()
Alternatively, you can use it in any other context property.
const { navigate } = usePloneProvider()
PloneClientProvider
PloneProvider
in a group of other smaller providers.
You can also instantiate and use them as standalone providers.
However, you should do this only if the framework has some limitation on using the bulk PloneClientProvider
.
The following snippets show its usage.
First, instantiate the provider.
export type PloneClientProviderProps = {
client: InstanceType<typeof PloneClient>;
queryClient: QueryClient;
children?: React.ReactNode;
};
Second, use its related hook through either of the following examples.
import { usePloneClient } from '@plone/providers';
const client = usePloneClient()
or
const { getContentQuery } = usePloneClient()
AppRouterProvider
This provider is included also in PloneProvider
.
You can also instantiate and use it as a standalone provider.
However, you should do this only if the framework has some limitation on using the bulk PloneClientProvider
.
The following code example shows its usage.
interface AppRouterProps {
useLocation: () => Location | undefined;
useParams: (opts?: any) => Record<string, string>;
navigate: (path: string) => void;
useHref?: (to: string, options?: any) => string;
flattenToAppURL: (path: string | undefined) => string | undefined;
children: ReactNode;
}
The following code sample shows its related hook.
import { useAppRouter } from '@plone/providers';
const { useLocation } = useAppRouter()