flooks

State Manager for React Hooks, Auto Optimized

Usage no npm install needed!

<script type="module">
  import flooks from 'https://cdn.skypack.dev/flooks';
</script>

README

flooks v5

State Manager for React Hooks, Auto Optimized.

npm GitHub Workflow Status Codecov npm bundle size npm type definitions GitHub

English · 简体中文


Features

  • Gorgeous auto optimized re-render
  • Automatic request loading
  • Interconnected stores
  • Extremely simple API

Install

yarn add flooks

# npm i flooks

Usage

import create from 'flooks';

const useCounter = create(({ get, set }) => ({
  count: 0,
  add() {
    const { count } = get();
    set({ count: count + 1 });
  },
  async addAsync() {
    await new Promise((resolve) => setTimeout(resolve, 1000));
    const { add } = get();
    add();
  },
}));

function Counter() {
  const { count, add, addAsync } = useCounter();

  return (
    <div>
      <p>{count}</p>
      <button onClick={add}>+</button>
      <button onClick={addAsync}>+~ {addAsync.loading && '...'}</button>
    </div>
  );
}

* Automatic request loading - if a function is async, asyncFn.loading is its loading state. If asyncFn.loading is not used, no extra re-render.

Demo

Edit flooks

Auto optimization

flooks realizes a gorgeous auto optimization, only actually used data will be injected into the component, re-render completely on demand, when React is truly "react".

Why flooks over zustand?

// zustand, need a selector
const { nuts, honey } = useStore((state) => ({ nuts: state.nuts, honey: state.honey }));

// flooks, no selector needed
// but also only `nuts` or `honey` update triggers re-render, it's automatic!
const { nuts, honey } = useStore();

Only functions, no re-render

const { a } = useStore(); // A component, update `a`
const { fn } = useStore(); // B component, only functions, no re-render

No updated state, no re-render

const { a } = useStore(); // A component, update `a`
const { b } = useStore(); // B component, no `a`, no re-render

No *.loading, no extra re-render

const { asyncFn } = useStore(); // A component, call `asyncFn`
asyncFn(); // No `asyncFn.loading`, no extra re-render

// With normal loading solutions, even `asyncFn.loading` is not used,
// it will re-render at least twice (turn `true` then `false`).

API

create()

import create from 'flooks';

const useStore = create(initStore);

get() & set()

import create from 'flooks';
import useOutStore from './useOutStore';

const useStore = create(({ get, set }) => ({
  fn() {
    const { a, b } = get(); // get own store
    const { x, y } = get(useOutStore); // get other stores

    set({ a: a + b }); // payload style
    // or
    set((state) => ({ a: state.a + state.b })); // function style
  },
}));

* Interconnected stores - call get(useOutStore) to get other stores, all stores can be connected.

From v4 to v5

- import useStore from 'flooks';
+ import create from 'flooks';

- import { outStore } from './useOutStore';
+ import useOutStore from './useOutStore';

- const counter = ({ get, set }) => ({
+ const useCounter = create(({ get, set }) => ({
    count: 0,
    add() {
-     const { count } = get(outStore);
+     const { count } = get(useOutStore);
    },
- });
+ }));

- const useCounter = () => useStore(counter);

  export default useCounter;

License

MIT License (c) nanxiaobei

FUTAKE

Try FUTAKE in WeChat. A mini app for your inspiration moments. 🌈

FUTAKE