npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

binia

v1.0.29

Published

react state manager

Downloads

13

Readme

inspired by valtio

Demo

install

npm i binia

Api

defineStore

定义 store, computed 属性也支持 setter, 注意由于使用 this 访问属性, 所以不能使用箭头函数

import { defineStore } from "binia";
const store = defineStore({
  state: { count: 1 },
  computed: {
    doubled() {
      return this.count * 2;
    },
    quadrupled: {
      get() {
        return this.doubled * 2;
      },
      set(v: number) {
        this.count = v >> 2;
      },
    },
  },
});

const state2 = defineStore({
  state: {
    firstName: "Alec",
    lastName: "Baldwin",
  },
  computed: {
    fullName: {
      get() {
        return this.firstName + " " + this.lastName;
      },
      set(newValue: string) {
        [this.firstName, this.lastName] = newValue.split(" ");
      },
    },
  },
});

options

computedCacheSize: 自定义computed的缓存大小, 默认2 demo

useSnapshot

在组件中使用 store 中的数据, useSnapshot 返回只读对象, 通过拦截 getter 收集组件中具体使用了那些属性, 只有被用到的属性发生变化后才会更新组件, 不需要使用 Context 或者 Provider 等 api

function C() {
  const { count, doubled, quadrupled } = useSnapshot(store);
  return (
    <div>
      <h2>count:{count}</h2>
      <h2>doubled:{doubled}</h2>
      <h2>quadrupled:{quadrupled}</h2>
    </div>
  );
}

action

action 就是一个简单的修改 store 的普通函数

const inc = () => store.count++;

const decAsync = async (v = 1) => {
  await sleep(1000);
  store.count -= v;
};

derive

用 derive 函数定义一个派生自多个 store 的新 store, 每个属性都是一个参数为 get 的函数, 访问时的属性值为函数返回值, 通过 get 函数收集依赖, 下面的案例中 storeC.c 变化后属性 ab 是不会变化的, 只有 storeA.a 或者 storeB.b 变化后 ab 才会更新, 对应的组件也会重新 render

const storeA = defineStore({ state: { a: 1 } });
const storeB = defineStore({ state: { b: 1 } });
const storeC = defineStore({ state: { c: 1 } });

const storeD = derive({
  ab(get) {
    return get(storeA).a + '--' + get(storeB).b + '--' + storeC.c;
  },
});

connect

可以在class组件中使用

const inc = () => {
  store.count++;
};
type Store = typeof store;
type Snap = Snapshot<Store>;
const mapState = (snap: Snap) => {
  return {
    c: snap.count,
    d: snap.quadrupled,
  };
};
type MapState = ReturnType<typeof mapState>;
type MapActions = ReturnType<typeof mapActions>;
type Props = { name: string };

const mapActions = (store: Store) => {
  return {
    inc,
    dec: () => {
      store.count--;
    },
  };
};

class A extends React.Component<MapActions & MapState & Props> {
  render() {
    return (
      <div>
        <h2>c:{this.props.c}</h2>
        <h2>d:{this.props.d}</h2>
        <button onClick={this.props.inc}>inc</button>
        <button onClick={this.props.dec}>dec</button>
      </div>
    );
  }
}

const C = connect(store, mapState, mapActions)(A);

devtools

安装Redux DevTools 插件, 然后调用devtools函数开启

import { devtools, defineStore } from 'binia';

const store = defineStore({
  state: { count: 1 },
  computed: {
    doubled() {
      return this.count * 2;
    },
    quadrupled: {
      get() {
        return this.doubled * 2;
      },
      set(v: number) {
        this.count = v >> 2;
      },
    },
  },
});
devtools(store, { name: 'demo',enabled: true })

TS 支持

自定义类型

有些时候自动类型推导会无法推导 union 等类型, 需要手动标注类型

const state: { mode: "dev" | "prod" } = { mode: "dev" };
const store = defineStore({ state });

// 或者使用as
const store = defineStore({ state: { mode: "dev" as "dev" | "prod" } });

在 derive 中访问 computed

由于 ts 的限制, 目前并不能在 derive 函数中访问自己的 computed 属性, 功能上支持, 只是类型推导上无法支持, 可以使用 as 规避, 或者使用 derive 函数创建新 store

const storeA = defineStore({
  state: { h: "hello", w: "world" },
  computed: {
    hw() {
      return this.h + " " + this.w;
    },
  },
});
const storeB = defineStore({
  state: { count: 1 },
  computed: {
    doubled() {
      return this.count * 2;
    },
  },
  derive: {
    helloCount(get) {
      return "hello: " + get(this).count + get(storeA).hw;
    },
    helloDouble(get) {
        // 使用as语法规避
      return 'hello: ' + get(this as unknown as { doubled: number }).doubled + get(storeA).hw
    },
  },
});


const storeC = derive({
  helloCount(get) {
    return 'hello: ' + get(store).count + get(storeA).hw;
  },
  helloDouble(get) {
    return 'hello: ' + get(store).doubled + get(storeA).hw;
  },
})