@jsonjoy.com/collaborative-react
v18.5.0
Published
JSON CRDT React.js hooks, components, and types
Readme
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
npm install json-joy @jsonjoy.com/collaborative-react reactWhat this package provides
- Context providers for
ModelandNodeApi - 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
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 (
<div>
<p>{root.title}</p>
<button onClick={() => title?.ins(title.view().length, '!')}>Append !</button>
</div>
);
}
export const App = () => (
<ModelCtx model={model}>
<TitleEditor />
</ModelCtx>
);Context API
Providers
ModelCtx: provides aModelvia contextNodeCtx: provides aNodeApivia context
When using ModelCtx, both the model and model.api are available to hooks.
Context hooks
useCtxModel()/useCtxNode(): optional context access (can returnundefined)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 tickuseModelView(model?): subscribe to model view snapshotuseModel(selector, model?): derive reactive values from modeluseModelTry(selector, model?): safe variant returningundefinedon selector error
Node hooks
useNodeEvents(event, listener, node?): subscribe to node events (self,child,subtree)useNodeEffect(event, listener, node?): effect wrapper with auto-unsubscribeuseNodeChange(event, node?): re-render on node change, returns lastChangeEventuseNode(node?, event?): subscribe and return nodeuseNodeView(node?, event?): subscribe and return node view
Path hooks
usePath(path, node?, event?): read nested node by pathusePathView(path, node?, event?): read nested node view by pathuseObj(path?, node?, event?): typed object node hookuseArr(path?, node?, event?): typed array node hookuseStr(path?, node?, event?): typed string node hook
Components
UseModel
Render-prop component that re-renders when model changes.
import {UseModel} from '@jsonjoy.com/collaborative-react';
<UseModel
model={model}
render={(m) => <pre>{JSON.stringify(m.api.view(), null, 2)}</pre>}
/>UseNode
Render-prop component that re-renders on node events.
import {UseNode} from '@jsonjoy.com/collaborative-react';
<UseNode
node={model.s.$}
event="subtree"
render={(node) => <pre>{JSON.stringify(node.view(), null, 2)}</pre>}
/>Notes
- Most hooks can infer the target model/node from context when used under
ModelCtxorNodeCtx. - Use strict hooks only when you know a provider is present.
useModelViewonly re-renders when the view identity changes, whileuseModelTickre-renders on every model change.
