React

Currently, the recommended pattern to set up a React app with Jazz is to create a separate file (for example, called jazz.tsx) in which:

  1. You create a new Jazz React app context, extracting and exporting Jazz hooks.

    import { createJazzReactApp } from "jazz-react"; const Jazz = createJazzReactApp(); export const { useAccount, useCoState } = Jazz;
    • You extract hooks here so they can be aware of a custom AccountSchema for your app once you start using one (see Accounts & Migrations).

      This way, accounts returned by the hooks will be correctly typed throughout your app. Simply import them from jazz.tsx wherever you need them.

      import { createJazzReactApp } from "jazz-react"; const Jazz = createJazzReactApp({ AccountSchema: MyAppAccount }); export const { useAccount, useCoState } = Jazz;
  2. You define a context providing component (typically called JazzAndAuth) that uses

    • the context provider of the Jazz React app context you just created

    • the hooks and default/custom UI of one of the Auth Methods.

    This is also where you specify the sync & storage server to connect to (see Sync and storage).

    import { createJazzReactApp } from "jazz-react"; const Jazz = createJazzReactApp(); export const { useAccount, useCoState } = Jazz; import { PasskeyAuthBasicUI, usePasskeyAuth } from "jazz-react"; function JazzAndAuth({ children }: { children: React.ReactNode }) { const [passkeyAuth, passKeyState] = usePasskeyAuth({ appName }); return ( <> <Jazz.Provider auth={passkeyAuth} peer="wss://cloud.jazz.tools/?key=you@example.com" > {children} </Jazz.Provider> <PasskeyAuthBasicUI state={passKeyState} /> </> ); }

With JazzAndAuth defined, you can wrap your app in it and then use the extracted and exported hooks within your App.

ReactDOM.createRoot(document.getElementById("root")!).render( <React.StrictMode> <JazzAndAuth> <App /> </JazzAndAuth> </React.StrictMode> );

Next.js

Client-side only

The easiest way to use Jazz with Next.JS is to only use it on the client side. You can ensure this by:

  • marking the jazz.tsx file as "use client"
"use client" import { createJazzReactApp } from "jazz-react"; const Jazz = createJazzReactApp(); export const { useAccount, useCoState } = Jazz; import { PasskeyAuthBasicUI, usePasskeyAuth } from "jazz-react"; function JazzAndAuth({ children }: { children: React.ReactNode }) { const [passkeyAuth, passKeyState] = usePasskeyAuth({ appName }); return ( <> <Jazz.Provider auth={passkeyAuth} peer="wss://cloud.jazz.tools/?key=you@example.com" > {children} </Jazz.Provider> <PasskeyAuthBasicUI state={passKeyState} /> </> ); }
  • marking any file with components where you use Jazz hooks (such as useAccount or useCoState) as "use client"

SSR use (experimental)

Pure SSR use of Jazz is basically just using jazz-nodejs (see Node.JS / Server Workers) inside Server Components.

Instead of using hooks as you would on the client, you await promises returned by CoValue.load(...) inside your Server Components.

TODO: code example

This should work well for cases like rendering publicly-readable information, since the worker account will be able to load them.

In the future, it will be possible to use trusted auth methods (such as Clerk, Auth0, etc.) that let you act as the same Jazz user both on the client and on the server, letting you use SSR even for data private to that user.

SSR + client-side (experimental)

You can combine the two approaches by creating

  1. A pure "rendering" component that renders an already-loaded CoValue (in JSON-ified form)

TODO: code example

  1. A "hydrating" component (with "use client") that
  • expects a pre-loaded CoValue as a prop (in JSON-ified form)
  • uses one of the client-side Jazz hooks (such as useAccount or useCoState) to subscribe to that same CoValue
  • passing the client-side subscribed state to the "rendering" component, with the pre-loaded CoValue as a fallback until the client receives the first subscribed state

TODO: code example

  1. A "pre-loading" Server Component that
  • pre-loads the CoValue by awaiting it's load(...) method (as described above)
  • renders the "hydrating" component, passing the pre-loaded CoValue as a prop

TODO: code example