相关文章推荐
兴奋的石榴  ·  Direct-to-S3 .NET ...·  4 月前    · 
风流的爆米花  ·  node.js创建 file.js ...·  4 月前    · 
首发于 Retalk

react-easy-contexts,以最简单的方式,添加多个 React Context

GitHub

只添加一个 React Context 的问题

在 React Hooks 项目中,我们已经基本不需要传统的 Redux 之类的状态管理工具,直接使用 React 自身的 Context 功能即可。

而在项目中,若只添加一个 Context,如果 state 过多,那么 state 间将没有隔离。

也就是每次更新 Context,都会触发所有 state 使用者的重渲染 —— 更新 x,只使用 y 的组件也会重渲染。

所以实际开发中,我们需要 添加多个 Context 对 state 进行隔离,只把相关的 state 放在一起。

添加多个 Context 的代码示例

const XContext = createContext({});
const YContext = createContext({});
const ZContext = createContext({});
const useX = () => useContext(XContext);
const useY = () => useContext(YContext);
const useZ = () => useContext(ZContext);
const XProvider = ({ children }) => {
  const [x, setX] = useState(0);
  const value = useMemo(() => ({ x, setX }), [x]);
  return <XContext.Provider value={value}>{children}</XContext.Provider>;
const YProvider = ({ children }) => {
  const [y, setY] = useState(0);
  const value = useMemo(() => ({ y, setY }), [y]);
  return <YContext.Provider value={value}>{children}</YContext.Provider>;
const ZProvider = ({ children }) => {
  const [z, setZ] = useState(0);
  const value = useMemo(() => ({ z, setZ }), [z]);
  return <ZContext.Provider value={value}>{children}</ZContext.Provider>;
const App = () => {
  return (
    <XProvider>
      <YProvider>
        <ZProvider>
          <AppMain />
        </ZProvider>
      </YProvider>
    </XProvider>

在上面的例子中,我们添加了 XContext YContext ZContext 3 个 Context。

这样开发,有什么体验不太好的地方呢?

—— 我们书写了大量的重复代码。

添加每个 Context 都得经历 createContext() ,复制粘贴 <XXXContext.Provider> ,以及加在 App 的操作。总之,需要书写大量的样板代码。

如果还要添加更多 Context 呢?只能不断去复制一模一样的工作。

如何简单的添加多个 Context?

而使用 react-easy-contexts 的话,上面的例子就可以变成这样:

import { create, useProvider } from 'react-easy-contexts';
const ctx = create({
  useX() {
    const [x, setX] = useState(0);
    return useMemo(() => ({ x, setX }), [x]);
  useY() {
    const [y, setY] = useState(0);
    return useMemo(() => ({ y, setY }), [y]);
  useZ() {
    const [z, setZ] = useState(0);
    return useMemo(() => ({ z, setZ }), [z]);
const App = () => {
  const Provider = ctx.useProvider();
  return (