@y-sweet/react
Library with a React context provider and React hooks for syncing a Yjs Doc.
Installation
npm install @y-sweet/react
<YDocProvider>
Wrap the root of your project with a <YDocProvider>
component, then descendants can use Y-Sweet’s React hooks: useMap
, useArray
, useText
, usePresence
, and usePresenceSetter
.
The YDocProvider
component takes a doc ID and an AuthEndpoint
as props. It also takes an initialClientToken
prop. If provided, the initialClientToken
will be used to start instead of fetching a ClientToken
. The YDocProvider
also takes an optional showDebuggerLink
prop (defaults to true
) which shows/hides a link to the Y-Sweet Debugger in the console.
import { YDocProvider } from '@y-sweet/react'
export function App() {
return (
<YDocProvider docId="my-doc-id" authEndpoint="/api/auth">
<MyCollaborativeApp />
</YDocProvider>
)
}
The AuthEndpoint
passed to the YDocProvider
is used to fetch a ClientToken
that authorizes the client to read and write to the shared document. The AuthEndpoint
may either be a
string (a full URL or just a path) or an async function that returns a ClientToken
. If you are using a meta-framework like NextJS or Remix, you can implement this auth endpoint as an API route, or you can use a server framework like ExpressJS or Hono.
Here’s an example of how the auth endpoint might be implemented using NextJS’s Route Handlers:
import { DocumentManager } from '@y-sweet/sdk'
import { NextResponse } from 'next/server'
const manager = new DocumentManager(process.env.CONNECTION_STRING)
export async function POST(request: Request) {
// In a production app, this is where you'd authenticate the user
// and check that they are authorized to access the doc.
const { docId } = await request.json()
const clientToken = await manager.getOrCreateDocAndToken(docId)
return NextResponse.json(clientToken)
}
useMap([name])
A React hook that returns the Yjs Shared Type Y.Map and rerenders when it is updated. It takes an optional name (a string
) to identify it within the Yjs document.
import { useMap } from '@y-sweet/react'
const sharedMap = useMap('my-map')
sharedMap.set('my-field', myValue)
sharedMap.get('my-field')
useArray([name])
A React hook that returns the Yjs Shared Type Y.Array and rerenders when it is updated. It takes an optional name (a string
) to identify it within the Yjs document.
import { useArray } from '@y-sweet/react'
const sharedArray = useArray('my-array')
sharedArray.push([1, 2, 3])
sharedArray.insert(0, [4, 5, 6])
sharedArray.delete(1, 1)
sharedArray.get(3)
sharedArray.toArray()
useText([name])
A React hook that returns the Yjs Shared Type Y.Text and rerenders when it is updated. It takes an optional name (a string
) to identify it within the Yjs document.
import { useText } from '@y-sweet/react'
const sharedText = useText('my-text')
sharedText.insert(0, 'abc')
sharedText.format(1, 2, { bold: true })
sharedText.toString()
sharedText.toDelta()
usePresence()
A React hook that returns a JavaScript Map
of client IDs to presence info (i.e. Record<string, any>
) that have been set with the usePresenceSetter()
hook. This hook also subscribes the component to presence changes, triggering a rerender when any client’s presence is updated.
import { usePresence } from '@y-sweet/react'
const presenceMap = usePresence()
for (const [clientId, presence] of presenceMap) {
// use each client's presence information to render avatars and/or shared cursors
}
usePresenceSetter()
A React hook that returns a function for setting a client’s own presence information, which is a Record<string, any>
.
import { usePresenceSetter } from '@y-sweet/react'
const setPresence = usePresenceSetter()
setPresence({
name: 'my-name',
color: '#62B4FF',
cursorX: 100,
cursorY: 100
})
useYjsProvider()
A React hook that returns the context’s YSweetProvider
.
import { useYjsProvider } from '@y-sweet/react'
const provider = useYjsProvider()
Types
type AuthEndpoint = string | () => Promise<ClientToken>
type ClientToken = {
url: string
baseUrl: string
docId: string
token?: string
}