# JSON CRDT integrations with React.js React hooks, context helpers, and lightweight render-prop components for binding React UI to `json-joy` CRDT models and nodes. ## Installation ```bash npm install json-joy @jsonjoy.com/collaborative-react react ``` ## What this package provides - **Context providers** for `Model` and `NodeApi` - **Reactive hooks** for model ticks, model views, node views, and path access - **Typed path hooks** for object/array/string nodes - **Render-prop components** (`UseModel`, `UseNode`) for declarative subscriptions ## Quick start ```tsx import * as React from 'react'; import {ModelCtx, useModelView, useStr} from '@jsonjoy.com/collaborative-react'; import {Model} from 'json-joy/lib/json-crdt'; const model = Model.create({title: 'Hello'}); function TitleEditor() { const root = useModelView(); const title = useStr('/title'); return (

{root.title}

); } export const App = () => ( ); ``` ## Context API ### Providers - `ModelCtx`: provides a `Model` via context - `NodeCtx`: provides a `NodeApi` via context When using `ModelCtx`, both the model and `model.api` are available to hooks. ### Context hooks - `useCtxModel()` / `useCtxNode()`: optional context access (can return `undefined`) - `useCtxModelStrict()` / `useCtxNodeStrict()`: strict access (throws if missing) ### Custom isolated context Use `createNodeCtx()` when you need a separate, isolated node/model context in the same component tree. ## Hooks ### Model hooks - `useModelTick(model?)`: subscribe to every model tick - `useModelView(model?)`: subscribe to model view snapshot - `useModel(selector, model?)`: derive reactive values from model - `useModelTry(selector, model?)`: safe variant returning `undefined` on selector error ### Node hooks - `useNodeEvents(event, listener, node?)`: subscribe to node events (`self`, `child`, `subtree`) - `useNodeEffect(event, listener, node?)`: effect wrapper with auto-unsubscribe - `useNodeChange(event, node?)`: re-render on node change, returns last `ChangeEvent` - `useNode(node?, event?)`: subscribe and return node - `useNodeView(node?, event?)`: subscribe and return node view ### Path hooks - `usePath(path, node?, event?)`: read nested node by path - `usePathView(path, node?, event?)`: read nested node view by path - `useObj(path?, node?, event?)`: typed object node hook - `useArr(path?, node?, event?)`: typed array node hook - `useStr(path?, node?, event?)`: typed string node hook ## Components ### `UseModel` Render-prop component that re-renders when model changes. ```tsx import {UseModel} from '@jsonjoy.com/collaborative-react';
{JSON.stringify(m.api.view(), null, 2)}
} /> ``` ### `UseNode` Render-prop component that re-renders on node events. ```tsx import {UseNode} from '@jsonjoy.com/collaborative-react';
{JSON.stringify(node.view(), null, 2)}
} /> ``` ## Notes - Most hooks can infer the target model/node from context when used under `ModelCtx` or `NodeCtx`. - Use strict hooks only when you know a provider is present. - `useModelView` only re-renders when the view identity changes, while `useModelTick` re-renders on every model change.