1.0.0 • Published 1 year ago

use-box-state v1.0.0

Weekly downloads
-
License
MIT
Repository
github
Last release
1 year ago

use-box-state

npm npm bundle size node

一个轻量级的组件树状态共享方案。

✨特性

  • 轻量,API简单化,支持快速跨组件共享状态
  • 支持异步action,修改状态简单化
  • 支持读写分离,更新粒度精确化
  • 用法接近原生的useState,类型提示友好

📦 安装

npm:

npm i imook

pnpm:

pnpm i imook

⚡快速开始

import useBoxState, { createBox } from "use-box-state"

const counterBox = createBox(0)


function Counter() {
   const [count, setCount] = useBoxState(counterBox)
  return (
    <div>
      count:{count}
      <button onClick={() => setCount(count + 1)}>
        +
      </button>
    </div>
  )
}

export default Counter

💡API

createBox(initialState)

createBox接收初始状态作为参数,返回一个Box对象。

useBoxState(box [, mapStateFn])

useBoxState接收上面createBox⬆️创建的Box对象和可选的mapStateFn函数作为参数, 返回和useState基本一致,一个state,以及更新state的函数。通过这种方式在状态变更会订阅更新。

mapStateFn

mapStateFn以state作为参数,返回自定义的状态,可用来定制更新和衍生状态,在状态改变时会对前后两次状态进行浅比较,有变化式才会更新。

const nameInfoBox = createBox({
  familyName: 'sun',
  givenName: 'wukong'
})

function NameInfo() {
  const [nameInfo, setNameInfo] = useBoxState(nameInfoBox)
  // 定制更新
  const [givenName, setNameInfo] = useBoxState(nameInfoBox, s => s.givenName)
  // 衍生状态
  const [fullName, setNameInfo] = useBoxState(nameInfoBox, s => `${s.givenName} ${s.familyName}`)
  return (
      <>
        <p>familyName: {nameInfo.familyName}</p>
        <p>givenName: {givenName}</p>
        <p>fullName: {fullName}</p>
        {fullName}
      </>
  )
}

useSetBoxState(box)

useSetBoxState接收上面createBox⬆️创建的Box对象作为参数,返回一个更新状态的函数,这种方式不会订阅更新,用法和useState返回的的第二个参数setState一致 。

🧐 设计动机

在React中,我们一般如何实现组件间的状态共享呢?本质上就是状态提升。

常见的做法,对于层级不深的组件,将共享状态提升到最近的公共父组件;对于全局组件树,使用Context在组件树间进行状态传递。

上面提到的场景和对应做法,在特定的场景下都有这很明显的弊端,因此我们可以试图设计一种实现状态提升的折衷方案,抽离组件间需要共享的状态,构建一个的公共的“虚拟组件Box”,将共享状态提升到Box中进行集中管理,于是use-box-state应运而生。

在上面👆 我们提到了“虚拟组件”、“数据流”等,为了更好的对比这些场景和方案,这里我们需要引入React官网的一个比喻: 如果你把一个以组件构成的树想象成一个 props 的数据瀑布的话,那么每一个组件的 state 就像是在任意一点上给瀑布增加额外的水源,但是它只能向下流动。

场景🧩方案🛠优点✅缺点❌
层级组件将共享状态提升到最近的公共父组件简单、数据流清晰层级过深的组件需要逐层透传、props、改造成本较大
全局组件树使用Context在组件树间进行状态传递相对简单(基于useContext)更新粒度太大、无法轻易实现读写分离
任何场景构建虚拟组件简单、快速在数据流中新增了“看不见”的水源

🙋‍♂️ Q&A

如何判断我是否需要使用use-box-state❓

  • 和React一直推荐的那样,use-box-state推崇尽量地将状态内敛化,因此你不一定需要使用它;只有当你的层级组件/全局组件树在共享状态时出现上述👆 的缺点时,它才有登场的必要。简而言之,充分利用React内置的API将状态内敛到合适的层级,只在有必要的情况下,权衡场景后使用合适的状态管理工具~

如何划分Box❓

  • 没有限制,推荐通过组件功能模块划分,在实践过程中,建议先确定需要哪些组件需要共享状态,然后根据功能(视图UI)进行划分,一个简单有效的方法就是对Box进行规范化地命名。

多个Box需要怎么放比较好管理❓

  • 没有限制,如果你的目录结构是文件类型(api、components、pages...)去划分的,则推荐将box放到box文件夹中统一管理;如果你的目录结构是通过对应的功能模块(user、order...)去划分的,根据就近原则,推荐放到对应的功能模块中管理。

🏗 TODO

  • 支持 React 18
  • 新增单元测试
  • 支持esm
  • 支持跨ifrme/应用通信
  • 新增devtools
  • 新增LOGO
1.0.0-beta.2

1 year ago

1.0.0

1 year ago

1.0.0-beta.1

1 year ago

1.0.0-beta.0

1 year ago

0.3.2

1 year ago

0.3.1

1 year ago

0.3.0

1 year ago

0.2.0

1 year ago

0.1.0

1 year ago