bey

Simple immutable state for React using Immer

  • Owner: jamiebuilds/bey
  • Platform:
  • License:: MIT License
  • Category::
  • Topic:
  • Like:
    0
      Compare:

Github stars Tracking Chart

bey

Simple immutable state for React using Immer

  • ~700B minified and gzipped (not including React & Immer)
  • Try it out alongside other state solutions
  • Heavily inspired by react-copy-write

Install

yarn add bey

Example

import React from 'react';
import { render } from 'react-dom';
import { state, update, Subscribe } from 'bey';

let counter = state({
  count: 0,
});

function increment() {
  update(counter, state => { state.count++ });
}

function decrement() {
  update(counter, state => { state.count-- });
}

function Counter() {
  return (
    <Subscribe to={counter} on={state => state.count}>
      {count => (
        <div>
          <button onClick={decrement}>-</button>
          <span>{count}</span>
          <button onClick={increment}>+</button>
        </div>
      )}
    </Subscribe>
  );
}

render(<Counter/>, window.root);

Run this example locally by cloning the repo
and running yarn example in the root directory.

Guide

state()

First you'll need to create some state containers for your app.

let counter = state({
  count: 0
});

Call state() with your initial state and you're good to go.

This returns a small object which we can subscribe to, update, and get
the current state from.

update()

You'll want to create some "actions" that will update your state when
called. These should just be plain functions that call update() inside.

let counter = state({
  count: 0
});

function increment() {
  update(counter, state => { state.count++; });
}

function decrement() {
  update(counter, state => { state.count--; });
}

When you call update() you'll pass your state container and an "updater"
function. Inside the "updater" function is just passed through to
Immer (You'll want to read about that
works).

You'll notice that inside the updater function you can just mutate whatever you
want. Don't mutate outside of the updater function though.

<Subscribe/>

Finally, you'll need a way to subscribe to state updates and re-render your
tree.

function Counter() {
  return (
    <Subscribe to={counter}>
      {state => <span>{state.count}</span>}
    </Subscribe>
  );
}

If you only need part of your state, you get pass an optional on prop which
selects just the state you care about and passes it through to the children
function.

function Counter() {
  return (
    <Subscribe to={counter} on={state => state.count}>
      {count => <span>{count}</span>}
    </Subscribe>
  );
}

This also acts as an optimization when you have a large state object but only
need to re-render when a nested value in that state object is updated.

If you need multiple values, you can return an object:

<Subscribe to={user} on={state => ({ name: state.name, username: state.username })}>
  {({ name, username }) => <span>{name} (@{username})</span>}
</Subscribe>

The same optimizations will apply using the same shallow equality check that
React uses.

Calling actions

Actions can be called at any time from any part of your app.

let counter = state({ count: 0 });

function increment() {
  update(counter, state => { state.count++; });
}

function Increment() {
  return <button onClick={increment}>+</button>;
}

Multiple instances of containers

If you need to create multiple instances of containers, wrap your state()
call in a factory:

let createCounter = () => {
  return state({ count: 0 });
};

Remember that your methods for updating state are just functions, don't be
afraid to write them however you need. So here we can pass the state object we
are updating as a parameter.

function increment(counter) {
  update(counter, state => { state.count++; });
}

function decrement(counter) {
  update(counter, state => { state.count--; });
}

Then inside your components where you call those methods, pass the state
objects in:

function Counter(props) {
  return (
    <Subscribe to={props.counter} on={state => state.count}>
      {count => (
        <div>
          <button onClick={() => decrement(props.counter)}>-</button>
          <span>{count}</span>
          <button onClick={() => increment(props.counter)}>+</button>
        </div>
      )}
    </Subscribe>
  );
}

function Counters(props) {
  return (
    <div>
      <Counter counter={createCounter()}/>
      <Counter counter={createCounter()}/>
    </div>
  );
}

Main metrics

Overview
Name With Ownerjamiebuilds/bey
Primary LanguageJavaScript
Program languageJavaScript (Language Count: 2)
Platform
License:MIT License
所有者活动
Created At2018-05-15 19:39:44
Pushed At2019-02-08 17:36:15
Last Commit At2018-09-11 10:58:14
Release Count2
Last Release Namev1.1.0 (Posted on 2018-06-11 18:00:34)
First Release Namev1.0.0 (Posted on 2018-05-15 12:40:23)
用户参与
Stargazers Count258
Watchers Count8
Fork Count9
Commits Count13
Has Issues Enabled
Issues Count0
Issue Open Count0
Pull Requests Count2
Pull Requests Open Count2
Pull Requests Close Count0
项目设置
Has Wiki Enabled
Is Archived
Is Fork
Is Locked
Is Mirror
Is Private