Skip to content

Latest commit

 

History

History
125 lines (102 loc) · 3.06 KB

readme.md

File metadata and controls

125 lines (102 loc) · 3.06 KB

React Better Model

Easy way to share state and events between components and services.

Installation:

npm i react-better-model

or

yarn add react-better-model

Usage

Minimal working example

import { useCallback } from "react"
import { createModel, Model } from "react-better-model"

// initial state
const helloWorldModelInitialState = {
	count: 0,
}

// model state type (usefull later)
type HelloWorldModelState = typeof helloWorldModelInitialState

// model event types (optional, if you want to use events)
type HelloWorldModelEvents = {
	click: number
}

// create your model class
class HelloWorldModelClass extends Model<HelloWorldModelState, HelloWorldModelEvents> {
	constructor(state = helloWorldModelInitialState){
		super(state)
	}
}

// create object that will contain hooks and refferences
// that you can use in your code
const HWM = createModel(HelloWorldModelClass)

// component with button that listens to and sets 'count' value
const ButtonAdd = HWM.withModel(({ model, ...props }) => {
	const [count, setCount] = model.useState('count')

	const onClick = useCallback(() => {
		setCount(count + 1)
	}, [count])

	// this is just an example of listening and setting value.
	// a better way (without listening) would be:
	// const onClick = useCallback(() => {
	// 	model.reduce((state) => {
	// 		return {
	// 			count: state.count + 1
	// 		}
	// 	})
	// }, [])

	return <button onClick={onClick}>increment count</button>
})

// Button that uses an event dispatcher
const ButtonClickEvent = HWM.withModel(({ model, ...props }) => {
	const [count] = model.useState('count')

	const dispatchClearEvent = model.useEvent('click')

	const clear = useCallback(() => {
		dispatchClearEvent(count)
	}, [count])

	return <button onClick={clear}>click to dispatch 'click' event</button>
})

// label with the current count value
const CountLabel = HWM.withModel(({ model, ...props }) => {
	const [count] = model.useState('count')

	return <p>current count is: {count}</p>
})

// convinience component to handle model events in one place
const EventHandler = HWM.withModel(({ model, ...props }) => {
	const handleClickEvent = useCallback((x: HelloWorldModelEvents['click']) => {
		alert(`clicked ${x} times`)
	}, [])

	model.useEvent('click', handleClickEvent)

	return null
})

// the widget itself wrapped in HelloWorldModel Provider
// any consumers (HWM.withModel(...)) rendered here
// are inside the same context.
// they can still use other models via useState hook
// created with createModel()
export const HelloWorldWidget = HWM.withProvider(({
	model,
	...props
}) => {
	return <>
		<EventHandler/>     {/* Event handling component */}
		<CountLabel />      {/* Label that displays updated count */}
		<ButtonAdd/>        {/* Button that increases the count */}
		<ButtonClickEvent/> {/* Button that dispatches 'click' event */}
	</>
})

Documentation

Model creation
Global models
State
Events

Example

Example project