React轻量状态管理库:unstated-next

2,266 阅读1分钟

unstated-next的github地址

背景

使用react Hooks后,想共享组件逻辑,可以自定义Hook。

除了共享逻辑外,想共享状态,可以用useContext。

unstated-next可以做到即共享组件逻辑,又共享状态。而且它比较小(unstated-next 用 40 行代码号称 React 数据管理库的终结版。),源码仅用了react。

unstated-next这个库只做了一件事:

1.提供createContainer将自定义Hooks封装为一个数据对象,提供Provider注入和useContainer获取Store这两个方法。

API

1. createContainer(useHook)

import { createContainer } from "unstated-next"

function useCustomHook() {
  let [value, setInput] = useState()
  let onChange = e => setValue(e.currentTarget.value)
  return { value, onChange }
}

let Container = createContainer(useCustomHook)
// Container === { Provider, useContainer }

2. <Container.Provider>

包含参数 initialState

function ParentComponent() {
  return (
    <Container.Provider initialState={2}>
      <ChildComponent />
    </Container.Provider>
  )
}

3. Container.useContainer()

此API同 useContainer(Container)一样

// Container.useContainer() 
function ChildComponent() {
  let input = Container.useContainer()
  return <input value={input.value} onChange={input.onChange} />
}
// useContainer(Container)
import { useContainer } from 'unstated-next';
function ChildComponent() {
  let input = useContainer(Container);
  return <input value={input.value} onChange={input.onChange} />
}

tips

  • 可以在其他 hooks 内部组合 containers
  • 保持containers小而集中
  • unstated-next 无需优化。需要优化的都是标准的react优化。

示例

这里是demo

import React, { useState } from "react"
import { createContainer } from "unstated-next"
import { render } from "react-dom"

function useCounter(initialState = 0) {
  let [count, setCount] = useState(initialState)
  let decrement = () => setCount(count - 1)
  let increment = () => setCount(count + 1)
  return { count, decrement, increment }
}

let Counter = createContainer(useCounter)

function CounterDisplay() {
  let counter = Counter.useContainer()
  return (
    <div>
      <button onClick={counter.decrement}>-</button>
      <span>{counter.count}</span>
      <button onClick={counter.increment}>+</button>
    </div>
  )
}

function App() {
  return (
    <Counter.Provider>
      <CounterDisplay />
      <Counter.Provider initialState={2}>
        <div>
          <div>
            <CounterDisplay />
          </div>
        </div>
      </Counter.Provider>
    </Counter.Provider>
  )
}

render(<App />, document.getElementById("root"))

unstated-next源码js版

import { createContext, useContext } from 'react';

export function createContainer(useHook) {
  const Context = createContext();

  const Provider = props => {
    const value = useHook(props?.initialState);
    return 
        <Context.Provider value={value}>{props.children}</Context.Provider>;
  };

  const useContainer = () => {
    const value = useContext(Context);
    return value;
  };

  return { Provider, useContainer };
}

export function useContainer(provider) {
  return provider.useContainer();
}

其他react状态管理库:mobx、dva、redux-toolkit、Recoil、Jotai、Zustand、Valtio.