mutik
mutik copied to clipboard
A tiny (495B) immutable state management library based on Immer

A tiny (495B) immutable state management library based on Immer
Quick Start
yarn add mutik
or
Table of Contents
- Example
-
API
-
createStore<S>(intialState: S): Store<S>
-
store
-
-
useSelector<S, V>(selector: (s: S) => V)
-
<Provider />
-
- Author
- Inspiration
Example
To use Mutik with React, you'll need to install React and React DOM from the experimental release channel because Mutik uses the recently-merged useMutableSource
hook internally.
yarn add react@experimental react-dom@experimental
import React from 'react';
import { render } from 'react-dom';
import { createStore, Provider, useSelector } from 'mutik';
// Create a lil' store with some state
let store = createStore({
count: 0,
});
// Pass the store to the Provider.
function App() {
return (
<Provider store={store}>
<div>
<Label />
<Buttons />
</div>
</Provider>
);
}
// You can mutate the store from anywhere you want to,
// even outside of React code. Mutate is based on immer.
function increment() {
store.mutate(state => {
state.count++;
});
}
// Or you can update it like React.useState's update
function decrement() {
store.set(prevState => ({
...prevState,
count: prevState.count - 1
});
}
// You don't need to pass the store down as a prop either
function Buttons() {
return (
<React.Fragment>
<button onClick={decrement}>-</button>
<button onClick={increment}>+</button>
</React.Fragment>
);
}
// Lastly, you can subcribe to "slices" of state with useSelector
// Note: be sure to memoize these with React.useCallback if you need to select based on props
function Label() {
const selector = React.useCallback(state => state.count, []);
const count = useSelector(selector);
return <p>The count is {count}</p>;
}
render(<App />, window.root);
API
createStore<S>(intialState: S): Store<S>
Create a Mutik store
given some initial state. The store
has the following API you can use in or out of React.
store
Method | Description |
---|---|
get() |
Get the current state. Do not use this inside of React, you should instead use useSelector |
set(nextState: S | (prevState: S) => V): void; |
Set state. This can either take a new value or and updater function (just like React.useState's updater) |
on(listener: Function): () => void; |
Subscribe to store. Pass in a callback function that will be executed on updates. on() returns the unsubscribe function for your convenience. |
off(listener: Function): void; |
Unsubscribe a given listener function |
reset(): void |
Set state back to the initialState used when creating the store |
mutate(updater: (draft: Draft) => void | S): void; |
Immer-style updater function. |
useSelector<S, V>(selector: (s: S) => V)
React hook to subscribe to Mutik state. Must be called underneath a Mutik Provider
.
const selector = state => state.count;
function Label() {
const count = useSelector(selector);
return <p>The count is {count}</p>;
}
You can use props with Mutik selector. For performance, it's a good idea to memoize the selector with React.useCallback
. For example:
function User({ id }) {
const selector = React.useCallback(state => state.users[id], [id]);
const user = useSelector(selector);
return <p>The username is {user.name}</p>;
}
<Provider />
Mutik context provider. Pass your store as store
prop. For example:
import React from 'react';
import { createStore, Provider } from 'mutik';
// Create a lil' store with some state
let store = createStore({
count: 0,
});
// Pass the store to the Provider.
function App() {
return (
<Provider store={store}>
<div>{/* ... stuff */}</div>
</Provider>
);
}
Author
- Jared Palmer @jaredpalmer
Inspiration
MIT License