UNPKG

pullstate

Version:

Simple state stores using immer and React hooks

137 lines (99 loc) 5.38 kB
<p align="center"> <img src="https://github.com/lostpebble/pullstate/raw/master/graphics/logo-newest.png" alt="Pullstate" /> </p> ### pullstate > Ridiculously simple state stores with performant retrieval anywhere > in your React tree using the wonderful concept of React hooks! * ~7KB minified and gzipped! (excluding Immer and React) * Built with Typescript, providing a great dev experience if you're using it too * Uses [immer](https://github.com/mweststrate/immer) for state updates - easily and safely mutate your state directly! * **NEW** - [Create async actions](https://lostpebble.github.io/pullstate/docs/async-actions-introduction) and use React hooks or `<Suspense/>` to have complete control over their UI states! _Originally inspired by the now seemingly abandoned library - [bey](https://github.com/jamiebuilds/bey). Although substantially different now- with Server-side rendering and Async Actions built in! Bey was in turn inspired by [react-copy-write](https://github.com/aweary/react-copy-write)._ Try out a quick example: [![Edit Pullstate Client-only Example](https://codesandbox.io/static/img/play-codesandbox.svg)](https://codesandbox.io/s/myvj8zzypp) ### 🎉 **[New documentation site is live!](https://lostpebble.github.io/pullstate/)** * [Installation](https://lostpebble.github.io/pullstate/docs/installation) * [Quick example](https://lostpebble.github.io/pullstate/docs/quick-example) * [Quick example - Server rendering](https://lostpebble.github.io/pullstate/docs/quick-example-server-rendered) * [Async Actions](https://lostpebble.github.io/pullstate/docs/async-actions-introduction) * [Creation](https://lostpebble.github.io/pullstate/docs/async-actions-creating) * [Usage](https://lostpebble.github.io/pullstate/docs/async-action-use) * [Async action hooks](https://lostpebble.github.io/pullstate/docs/async-hooks-overview) --- # **Let's dive right in** > This is taken directly from [the documentation site](https://lostpebble.github.io/pullstate/docs/quick-example), to give you a quick overview of Pullstate here on github. Be sure to check out the site to learn more. To start off, install `pullstate`. ```bash yarn add pullstate ``` ## Create a store Define the first **state store**, by passing an initial state to `new Store()`: <!--JavaScript--> ```jsx import { Store } from "pullstate"; export const UIStore = new Store({ isDarkMode: true, }); ``` ## Read our store's state Then, in React, we can start using the state of that store using a simple hook `useState()`: ```tsx import * as React from "react"; import { UIStore } from "./UIStore"; export const App = () => { const isDarkMode = UIStore.useState(s => s.isDarkMode); return ( <div style={{ background: isDarkMode ? "black" : "white", color: isDarkMode ? "white" : "black", }}> <h1>Hello Pullstate</h1> </div> ); }; ``` The argument to `useState()` over here (`s => s.isDarkMode`), is a selection function that ensures we select only the state that we actually need for this component. This is a big performance booster, as we only listen for changes (and if changed, re-render the component) on the exact returned values - in this case, simply the value of `isDarkMode`. --- ## Add interaction (update state) Great, so we are able to pull our state from `UIStore` into our App. Now lets add some basic interaction with a `<button>`: ```tsx return ( <div style={{ background: isDarkMode ? "black" : "white", color: isDarkMode ? "white" : "black", }}> <h1>Hello Pullstate</h1> <button onClick={() => UIStore.update(s => { s.isDarkMode = !isDarkMode; }) }> Toggle Dark Mode </button> </div> ); ``` Notice how we call `update()` on `UIStore`, inside which we directly mutate the store's state. This is all thanks to the power of `immer`, which you can check out [here](https://github.com/immerjs/immer). Another pattern, which helps to illustrate this further, would be to actually define the action of toggling dark mode to a function on its own: <!--JavaScript--> ```tsx function toggleMode(s) { s.isDarkMode = !s.isDarkMode; } // ...in our <button> code <button onClick={() => UIStore.update(toggleMode)}>Toggle Dark Mode</button> ``` Basically, to update our app's state all we need to do is create a function (inline arrow function or regular) which takes the current store's state and mutates it to whatever we'd like the next state to be. ## Omnipresent state updating Something interesting to notice at this point is that we are just importing `UIStore` directly and running `update()` on it: ```tsx import { UIStore } from "./UIStore"; // ...in our <button> code <button onClick={() => UIStore.update(toggleMode)}>Toggle Dark Mode</button> ``` And our components are being updated accordingly. We have freed our app's state from the confines of the component! This is one of the main advantages of Pullstate - allowing us to separate our state concerns from being locked in at the component level and manage things easily at a more global level from which our components listen and react (through our `useStoreState()` hooks).