Project Name | Stars | Downloads | Repos Using This | Packages Using This | Most Recent Commit | Total Releases | Latest Release | Open Issues | License | Language |
---|---|---|---|---|---|---|---|---|---|---|
Mobx | 26,321 | 9,267 | 3,766 | 12 hours ago | 236 | September 07, 2022 | 35 | mit | TypeScript | |
Simple, scalable state management. | ||||||||||
Formily | 9,334 | 119 | 7 days ago | 209 | September 20, 2022 | 11 | mit | TypeScript | ||
📱🚀 🧩 Cross Device & High Performance Normal Form/Dynamic(JSON Schema) Form/Form Builder -- Support React/React Native/Vue 2/Vue 3 | ||||||||||
Mobx State Tree | 6,651 | 479 | 259 | 18 days ago | 107 | August 09, 2022 | 201 | mit | TypeScript | |
Full-featured reactive state management without the boilerplate | ||||||||||
Mobx React | 4,676 | 29 | 4 | 2 years ago | 28 | February 23, 2016 | mit | TypeScript | ||
React bindings for MobX | ||||||||||
Rxjs Hooks | 2,136 | 12 | 24 | a month ago | 19 | June 19, 2022 | 20 | TypeScript | ||
React hooks for RxJS | ||||||||||
Mobx React Lite | 2,032 | 2 years ago | mit | TypeScript | ||||||
Lightweight React bindings for MobX based on React 16.8 and Hooks | ||||||||||
Rxviz | 1,535 | 3 months ago | 30 | mit | JavaScript | |||||
Rx Visualizer - Animated playground for Rx Observables | ||||||||||
Mobx React Form | 1,077 | 107 | 26 | a day ago | 198 | June 19, 2022 | 45 | mit | TypeScript | |
Reactive MobX Form State Management | ||||||||||
Redux Rx | 1,020 | 27 | 2 | 7 years ago | 6 | November 09, 2015 | 12 | JavaScript | ||
RxJS utilities for Redux. | ||||||||||
Luna | 983 | 10 months ago | 9 | gpl-3.0 | JavaScript | |||||
Manage npm dependencies through a modern UI. |
A predictable & observable state container for React apps
npm install react-restore
A store
holds the state
of the application and the actions
used to update
that state
import Restore from 'react-restore'
import * as actions from './actions'
let initialState = {text: 'Hello World'}
let store = Restore.create(initialState, actions)
Now we have a store!
To get the text
value from the store
store('text') // 'Hello World'
actions
are used to make updates to the state of the store
actions
are passed as an object during the store
's creationactions
object can be created explicitly or by using import syntax
import * as actions from './actions'
actions
contain the whole lifecycle of an update making async updates easy to create and trackLet's create an action called setText
to update
the text
value in our store
export const setText = (update, newText) => {
update(state => {
state.text = newText
return state
})
}
setText
can now be called via the store
store.setText('Updated World')
This would update the value text
in the store
to 'Updated World'
actions
are passed update
as their first argument (followed by any arguments you passed to them)update
method is how we replace values held by the store
update
method uses a pure updater function to perform these updatesIf you look back at our setText
action
you can see our updater
function
state => {
state.text = newText
return state
}
The updater
function is passed the state
(or more likely, part of the state
) and returns an updated version of it
update
takes a dot notation path as an optional first argumentstate
instead of the whole state
For example, our setText
action
could be
export const setText = (update, newText) => {
update('text', text => {
return newText
})
}
Targeting a more complex state
import Restore from 'react-restore'
import * as actions from './actions'
let initialState = {
nested: {
wordOne: 'Hello',
wordTwo: 'World'
}
}
let store = Restore.create(initialState, actions)
Let's create an action
called setNestedText
to update
wordTwo
in our store
export const setNestedText = (update, newValue) => {
update('nested.wordTwo', wordTwo => newValue)
}
Calling it is the same as before
store.setNestedText('Updated World')
This would update
the value of wordTwo
from 'World'
to 'Updated World'
Multi-arg Paths
Instead of concatenating a string for the path passed to store
or update
, you can define your path with multiple arguments. For example if you had an id (let id = 123
) for an item within the state you could break the path into multiple arguments, like so...
let name = store('items', id, 'name') // Gets the value of items[id].name from the store
// When updating, the last argument is always the updater function
update('items', id, 'name', name => 'bar') // Updates the value of items[id].name to 'bar'
Connecting React components to the store
is easy
Restore.connect(Component)
store
via this.store
store
changesstore
of its closest connected parentstore
, since it has no parent to inherit fromstore
will be passed down to your other connected componentsstore
for your appRestore.connect(Component, store) // Explicitly connects store to Component
Restore.connect(Component) // Component inherits store from closest parent Component
To access the store
from within a connected component, we do the same as before but this time referencing this.store
this.store('text')
// or
this.store.setText('Updated World')
Actions can contain synchronous and asynchronous updates, both are tracked and attributed to the action throughout its lifecycle. Here we'll make our setText
action get the newText
value from the server and then update the state asynchronously.
export const setText = update => {
getTextFromServer(newText => {
update('text', text => newText)
})
}
It can be useful to compose synchronous and asynchronous updates together. Say you wanted to show a loading message while you fetched the newText
value from the server. You could update a loading
flag synchronously and then unset it later when you get the response.
export const setText = update => {
update('loading', loading => true)
getTextFromServer(newText => {
update('loading', loading => false)
update('text', text => newText)
})
}
Restore has a <DevTools />
component you can use to observe updates to the state and time travel through past actions
npm install restore-devtools --save-dev
import DevTools from 'restore-devtools'
Drop <DevTools />
anywhere in your application to enable the dev tools
Connected components are observers
but you can use this functionality outside of components too!
store.observer(() => {
console.log(store('text'))
})
This function will run once immediately and again anytime the values it consumes change, in this case our text
value
App.jsx
import React from 'react'
import Restore from 'react-restore'
class App extends React.Component {
render () {
return (
<div onClick={() => this.store.setText('Updated World')}>
{this.store('text')}
</div>
)
}
}
export default Restore.connect(App)
actions.js
export const setText = (update, newText) => {
update('text', text => {
return newText
})
}
index.js
import React from 'react'
import ReactDOM from 'react-dom'
import Restore from 'react-restore'
import App from './App.jsx'
import * as actions from './actions.js'
let initialState = {text: 'Hello World'}
let store = Restore.create(initialState, actions)
let Root = Restore.connect(App, store)
ReactDOM.render(<Root />, document.getElementById('root'))