Skip to content

Latest commit

 

History

History
127 lines (89 loc) · 3.36 KB

File metadata and controls

127 lines (89 loc) · 3.36 KB

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 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

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 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.

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 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.