10 行代码复刻 constate 库

480 阅读2分钟

constate 可以说是我最喜欢的 react 库了,他的作用就是可以轻易的创建 context provider。我一般在实现一个代码量稍大一点的组件时,都会用它在外面包一层,因为这样可以让我不用层层传递 props,也可以顺便把视图与状态分离。

这是官网的 demo,没用过的朋友大概看一眼就知道了怎么回事了

import React, { useState } from "react";
import constate from "constate";

// 1️⃣ Create a custom hook as usual
function useCounter() {
  const [count, setCount] = useState(0);
  const increment = () => setCount((prevCount) => prevCount + 1);
  return { count, increment };
}

// 2️⃣ Wrap your hook with the constate factory
const [CounterProvider, useCounterContext] = constate(useCounter);

function Button() {
  // 3️⃣ Use context instead of custom hook
  const { increment } = useCounterContext();
  return <button onClick={increment}>+</button>;
}

function Count() {
  // 4️⃣ Use context in other components
  const { count } = useCounterContext();
  return <span>{count}</span>;
}

function App() {
  // 5️⃣ Wrap your components with Provider
  return (
    <CounterProvider>
      <Count />
      <Button />
    </CounterProvider>
  );
}

export default App;

然后我今天再写一个 react 19 的 demo,发现居然不支持安装,因为限制了必须要 18 版本之内

"peerDependencies": {
    "react": "^16.8.0 || ^17.0.0 || ^18.0.0"
  }

那我没办法了就准备自己搞一个,看了一下他的源码,源码非常简单,基本没有什么太难的封装和抽象。一共不到 90 行就写完了。查看源码

constate 支持 selector,这个我一般不用,所以我复刻的时候就给这部分省略掉了

一共10 行代码搞定

export const myConstate = <Props, Value>(useHook: (props: Props) => Value) => {
  const context = createContext<Value>({} as Value);
  let hook = () => {
    return useContext(context);
  };
  const Provider: FC<PropsWithChildren<Props>> = ({ children, ...props }) => {
    const value = useHook(props as Props);
    return <context.Provider value={value}>{children}</context.Provider>;
  };
  return [Provider, hook] as const;
};

测试一下

(此处原本有视频,因为掘金发视频很麻烦,我就给转成了 gif,改成 gif 之后无法保存无法发布,还没有报错,这个平台是真不行,想看效果可以在点击文章最后的在线 demo)

符合预期🎉🎉🎉

由于原理过于简单,以至于我想讲一下都不知道讲什么,就不讲了

查看 myConstate 在线示例