diff --git a/docs/core/shared/_installation.mdx b/docs/core/shared/_installation.mdx index 3fe14137d35b..e26f4cc5c6b3 100644 --- a/docs/core/shared/_installation.mdx +++ b/docs/core/shared/_installation.mdx @@ -3,6 +3,7 @@ import TabItem from '@theme/TabItem'; import PkgTabs from '@site/src/components/PkgTabs'; import PkgInstall from '@site/src/components/PkgInstall'; import Link from '@docusaurus/Link'; +import ProviderSetupCode from '@site/src/components/ProviderSetupCode'; ::::react @@ -19,16 +20,7 @@ values={[ -```tsx title="index.tsx" -import { DataProvider } from '@data-client/react'; -import { createRoot } from 'react-dom/client'; - -createRoot(document.body).render( - - - , -); -``` + Alternatively [integrate state with redux](../guides/redux.md) @@ -36,17 +28,7 @@ Alternatively [integrate state with redux](../guides/redux.md) -```tsx title="index.tsx" -import { DataProvider } from '@data-client/react'; -import { AppRegistry } from 'react-native'; - -const Root = () => ( - - - -); -AppRegistry.registerComponent('MyApp', () => Root); -``` + Alternatively [integrate state with redux](../guides/redux.md) @@ -58,43 +40,13 @@ Alternatively [integrate state with redux](../guides/redux.md) Full NextJS Guide -```tsx title="app/layout.tsx" -// highlight-next-line -import { DataProvider } from '@data-client/react/nextjs'; - -export default function RootLayout({ children }) { - return ( - - - // highlight-next-line - {children} - - - ); -} -``` + + -```tsx title="app/_layout.tsx" -import { Stack } from 'expo-router'; -import { DataProvider } from '@data-client/react'; - -export default function RootLayout() { - return ( - // highlight-start - - // highlight-end - - - - // highlight-start - - // highlight-end - ); -} -``` + @@ -118,21 +70,8 @@ Anansi includes Reactive Data Client automatically. -```tsx title="main.ts" -import { createApp } from 'vue'; -import { DataClientPlugin } from '@data-client/vue'; - -const app = createApp(App); + -app.use(DataClientPlugin, { - // optional overrides - // managers: getDefaultManagers(), - // initialState, - // Controller, - // gcPolicy, -}); - -app.mount('#app'); -``` +`app.use(DataClientPlugin, options)` optionally overrides [`managers`](../api/getDefaultManagers.md), `initialState`, `Controller`, and `gcPolicy`. :::: diff --git a/website/src/components/ProviderSetupCode.tsx b/website/src/components/ProviderSetupCode.tsx index 8a66cd4f4060..64d6ac164446 100644 --- a/website/src/components/ProviderSetupCode.tsx +++ b/website/src/components/ProviderSetupCode.tsx @@ -3,105 +3,140 @@ import type { ReactNode } from 'react'; import { parseCodeDocuments } from './Playground/editor/codeModel'; +interface Setup { + title: string; + imports: string[]; + body: string; +} + const PLATFORMS = { - web: { + web: (names, managers) => ({ title: 'index.tsx', - imports: (names: string[]) => [ + imports: [ ...importLine(['DataProvider', ...names], '@data-client/react'), "import { createRoot } from 'react-dom/client';", ], body: `createRoot(document.body).render( - + , );`, - }, - native: { + }), + native: (names, managers) => ({ title: 'index.tsx', - imports: (names: string[]) => [ + imports: [ ...importLine(['DataProvider', ...names], '@data-client/react'), "import { AppRegistry } from 'react-native';", ], body: `const Root = () => ( - + ); AppRegistry.registerComponent('MyApp', () => Root);`, - }, - nextjs: { - title: 'app/Provider.tsx', - imports: (names: string[]) => [ - "'use client';", - ...importLine(names, '@data-client/react'), - "import { DataProvider } from '@data-client/react/nextjs';", - ], - body: `export default function Provider({ + }), + // managers are client-only, so they need their own 'use client' Provider + nextjs: (names, managers) => + managers ? + { + title: 'app/Provider.tsx', + imports: [ + "'use client';", + ...importLine(names, '@data-client/react'), + "import { DataProvider } from '@data-client/react/nextjs';", + ], + body: `export default function Provider({ children, }: { children: React.ReactNode; }) { return {children}; }`, - }, - expo: { + } + : { + title: 'app/layout.tsx', + imports: ["import { DataProvider } from '@data-client/react/nextjs';"], + body: `export default function RootLayout({ children }) { + return ( + + + {children} + + + ); +}`, + }, + expo: (names, managers) => ({ title: 'app/_layout.tsx', - imports: (names: string[]) => [ + imports: [ "import { Stack } from 'expo-router';", ...importLine(['DataProvider', ...names], '@data-client/react'), ], body: `export default function RootLayout() { return ( - + ); }`, - }, - vue: { + }), + vue: (names, managers) => ({ title: 'main.ts', - imports: (names: string[]) => [ + imports: [ "import { createApp } from 'vue';", ...importLine(['DataClientPlugin', ...names], '@data-client/vue'), "import App from './App.vue';", ], body: `const app = createApp(App); -app.use(DataClientPlugin, { managers }); +app.use(DataClientPlugin${managers ? ', { managers }' : ''}); app.mount('#app');`, - }, -}; + }), +} satisfies Record Setup>; /** - * App setup file that passes `managers` to DataProvider (React) or - * DataClientPlugin (Vue). Used by docs/core/shared/_provider_managers.mdx + * App setup file that renders DataProvider (React) or DataClientPlugin (Vue), + * passing `managers` when given. + * Used by docs/core/shared/_provider_managers.mdx and _installation.mdx * * @param imports names imported from `@data-client/react` or `@data-client/vue` - * @param children code block defining `managers` + * @param children optional code block defining `managers` */ export default function ProviderSetupCode({ platform, - imports, + imports = [], children, }: { platform: keyof typeof PLATFORMS; - imports: string[]; - children: ReactNode; + imports?: string[]; + children?: ReactNode; }) { - const managers = parseCodeDocuments(children)[0]?.value; - // nothing to show without a managers block (e.g. the partial rendered alone) - if (!managers) return null; - const { title, imports: importLines, body } = PLATFORMS[platform]; + const managers = + children ? parseCodeDocuments(children)[0]?.value : undefined; + if (children && !managers) + throw new Error(' children must be a code block'); + const { + title, + imports: importLines, + body, + } = PLATFORMS[platform](imports, !!managers); + const header = importLines.join('\n'); // the managers block's own imports continue the import list - const gap = managers.startsWith('import ') ? '\n' : '\n\n'; + const sep = managers?.startsWith('import ') ? '\n' : '\n\n'; return ( - {`${importLines(imports).join('\n')}${gap}${managers}\n\n${body}`} + {managers ? + `${header}${sep}${managers}\n\n${body}` + : `${header}\n\n${body}`} ); } +function managersProp(managers: boolean) { + return managers ? ' managers={managers}' : ''; +} + /** Matches prettier's import wrapping at printWidth 80 */ function importLine(names: string[], pkg: string): string[] { if (!names.length) return [];