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

xsta

v2.1.0

Published

An ultra-lightweight (<200 lines) React state management solution with zero learning curve and migration costs.

Downloads

2,923

Readme

XSta Logo

NPM Version Minizipped Size Downloads FOSSA Status

XSta 是一个超轻量(< 200 lines)的 React 状态管理库,它提供了与原生 useState Hook 一致的状态管理接口,零学习、迁移成本,给你极致丝滑的 React 状态管理新体验。

✨ 亮点

  • 🐦 麻雀虽小,五脏俱全 核心不到 200 行代码(包含换行和注释),提供了完备的 React 状态管理解决方案,生产环境可用。
  • ✅ 让 React 状态管理变简单 只需将 useState 替换为 useXState,即可将组件内状态快速共享给其他父子、兄弟组件使用,就这么简单!
  • 💪 专注性能优化 内置状态选择器,确保各个组件只在其关注的状态改变时,才触发 re-render,轻松搞定复杂页面性能优化。
  • 🧩 零学习、迁移成本 可与项目中其他已使用的状态管理库共存,轻松切换,迁移无忧。

📦 安装

# With npm
npm install xsta

# With pnpm
pnpm install xsta

# With Yarn
yarn add xsta

⚡️ 快速上手

你只需要将 useState 替换为 useXState,并提供一个独一无二的 key

即可将组件内的本地状态快速共享为其他父子或兄弟组件都可以访问和修改的全局状态

import { useXState } from 'xsta';

export default function Counter() {
  // 将 useState 替换为 useXState,并绑定一个独一无二的 key
  const [count, setCount] = useXState('count', 0);

  function handleClick() {
    setCount(count + 1);
  }

  return (
    <button onClick={handleClick}>
      <p>You pressed me {count} times</p>
    </button>
  );
}

你也可以通过 XSta 在组件外的任意位置直接访问和修改指定状态,当外部状态变更时,依赖此状态的组件会自动更新。

import { useXState, XSta } from 'xsta';

function externalFunction() {
  // 获取状态
  const count = XSta.get('count');
  // 更新状态(会自动触发 Counter 组件 re-render)
  XSta.set('count', count + 1);
}

export default function Counter() {
  const [count] = useXState('count', 0);

  return (
    <button onClick={externalFunction}>
      <p>You pressed me {count} times</p>
    </button>
  );
}

💎 最佳实践

在开发过程中,为了更好的管理状态,通常会按照模块划分,封装各个状态相关的操作。

对此,XStaManager 对外提供了基础的状态管理接口,下面是 createXStaManager 的一个简单示例。

// counter.state.ts
import { createXStaManager } from 'xsta';

export const CounterState = createXStaManager({
  key: 'count',
  initialState: 0,
});

// Counter.ts
import { CounterState } from 'counter.state';

function externalFunction() {
  CounterState.setState(count => count + 1);
}

export default function Counter() {
  const [count] = CounterState.useState();

  return (
    <button onClick={externalFunction}>
      <p>You pressed me {count} times</p>
    </button>
  );
}

更进一步的,你也可以继承 XStaManager,然后对外提供统一的状态管理接口。(推荐)

// counter.state.ts
import { XStaManager } from 'xsta';

class _CounterState extends XStaManager<number> {
  key = 'count';
  initialState = 0;

  get oddOrEven() {
    return this.getState() & 1 ? 'odd' : 'even';
  }

  increase = () => {
    this.setState(count => count + 1);
  };

  decrease = () => {
    this.setState(count => count - 1);
  };
}

export const CounterState = new _CounterState();

// Counter.ts
import { CounterState } from 'counter.state';

export default function Counter() {
  const [count] = CounterState.useState();

  return (
    <>
      <p>You pressed me {count} times</p>
      <p>Count is {CounterState.oddOrEven}</p>
      <button onClick={CounterState.increase}>Increase</button>
      <button onClick={CounterState.decrease}>Decrease</button>
    </>
  );
}

⚙️ 高级选项

XConsumer

如果某个组件的构建比较昂贵,或者你的状态是一个复杂对象,有多个组件分别依赖它的不同属性:

比如一个公共的用户 profile 对象,用户头像组件只关心 avatar,用户简介组件只关心 bio 等

此时,你可以用 XConsumer 将需要性能优化的组件包裹起来,然后通过状态选择器(selector)控制子组件 re-render 的时机。

import { useXState, XConsumer } from 'xsta';

export default function UserProfile() {
  const [profile, setProfile] = useXState('profile', {
    avatar: 'https://github.com/fluidicon.png',
    age: 18,
    bio: 'hello world!',
  });

  console.log('UserProfile rebuild', profile);

  return (
    <>
      <XConsumer provider="profile" selector={s => s.avatar}>
        <UserAvatar /> {/* 当 avatar 改变时,UserAvatar 才会 re-render */}
      </XConsumer>
      <XConsumer provider="profile" selector={s => [s.age, s.bio]}>
        {profile => {
          // 你也可以直接访问当前的状态值
          return <UserInfo age={profile.age} bio={profile.bio} />;
        }}
      </XConsumer>
    </>
  );
}

useConsumer

useXConsumeruseXState 的一个别名,可以用来更方便的订阅状态更新。

import { useXConsumer } from 'xsta';

function WatchText() {
  // 当 myState.text 改变时,此组件会自动更新
  const [state] = useXConsumer('myState', s => s.text);
  return <p>Current text: {state.text}</p>;
}

更多功能

除了上面列举的常用功能之外,XSta 还提供了以下方法:

  • useXProvider(key, initialState): 初始化状态值
  • XSta.delete(key): 删除一个全局状态
  • XSta.clear(key): 清空所有的状态
import { useXState, useXProvider, XSta } from 'xsta';

const initialState = 0;

export default function APP() {
  // 初始化状态
  useXProvider('count', initialState);

  return (
    <>
      <CountViewer />
      <Increase />
      <Clear />
    </>
  );
}

function Clear() {
  return (
    <button
      onClick={() => {
        // 删除 "count" 状态
        XSta.delete('count');
        // 清空所有状态
        XSta.clear();
      }}
    >
      Clear
    </button>
  );
}

function CountViewer() {
  const [count] = useXState('count');

  return <p>You pressed me {count ?? initialState} times</p>;
}

function Increase() {
  return (
    <button
      onClick={() => {
        XSta.set('count', XSta.get('count', initialState) + 1);
      }}
    >
      Increase
    </button>
  );
}

注意:默认情况下 XSta 不会主动初始化或回收全局状态,而是由使用者决定状态值的初始化和销毁时机。所以在使用时请务必小心,防止状态尚未初始化,或内存泄漏等问题。