繁体   English   中英

使用带有自定义钩子的 useContext 与 useContext + useReducer

[英]using useContext with custom hooks vs useContext + useReducer

我最近进入了一个项目,在 react 中的 useContext 时看到了一些我以前没有见过的东西。

项目中的全局 state 使用它发送到上下文的钩子,然后当稍后在全局 state 上调用该钩子时,它是可访问的。 我看到的问题是在一个地方没有定义的全局 state,您可以使用 state 创建一个挂钩并更新功能,将其发送给提供商并在项目中的任何位置访问它。

代码:

const initialState = {
  id: "MyId",
  currency: 'currency',
};


function useCurrencyState() {
  initialState.currency = 'newCurrency'
  const [currency, setCurrency] = React.useState(initialState);

  return {
    currency
  };
}


export const [useCurrency, CurrencyStoreProvider] = createStoreProvider(useUserState);

提供者:

export function createStoreProvider(useHook) {
  const [useContextConsumer, ContextProvider] = generateContext();

  const StoreProvider = ({ children }) => {
    const state = useHook();

    return <ContextProvider value={state}>{children}</ContextProvider>;
  };

  return [useContextConsumer, StoreProvider];
}

生成上下文函数:

export function generateContext() {
  const context = React.createContext(undefined);

  const useContextConsumer = () => {
    const c = React.useContext(context);
    if (!c) {
      throw new Error('Component must be wrapped with <Container.Provider>');
    }
    return c;
  };

  return [useContextConsumer, context.Provider];
}

商店:

const StoreProvider = ({ children }) => (
  <CurrencyStoreProvider>
      {children}
  </CurrencyStoreProvider>
);

export default StoreProvider;

当你想使用 useCurrency 时,你会

import { useCurrency } from 'store/currency';

 const { currency} = useCurrency ();

上面的例子是一个钩子。 该项目有 8 个遵循相同的模式,并且该项目有 8 个嵌套提供程序。

我对此的初步想法是,它正在匿名变异 state,因为它没有全局定义的 state 并且没有减速器捕捉动作以更新全局 Z9ED39E2EA931586B73A985A6942EZEF5。

我对吗? 这是处理 state 的不那么推荐的方法吗? 如果我穿了这个图案,如果它有名字,它叫什么?

我正要建议更改为使用带有动作和调度的上下文 + useReducer,但我需要更好地理解上述内容。

上面提供的代码示例有两个部分。 一是 state 管理(使用useState完成,二是 state 提供者(使用上下文完成)。让我们分别讨论。

一般来说, useStateuseReducer和 Redux 减速机都是一样的。 它们都允许拥有一些 state 并基于它渲染组件。 它们在允许操作 state 的方式上有所不同,尤其是在复杂情况下。

  1. useState是一种最简单的方法。 你所能做的就是
  const [state, setState] = useState()
  setState(/* some new state */)
  // or
  setState(prevState => ({ ...prevState, /* some new state */ }))

操作 state 时很难添加逻辑。 即,如果您想在调用setCurrency之前进行货币转换,您应该在某处进行,或者编写自定义挂钩。 这个自定义钩子将是您执行 Redux 操作。

执行异步代码(获取货币汇率)将更加困难。 不要忘记在useEffect中获取速率是不够的,因为您必须处理服务器错误(5xx 或 4xx)并向用户显示适当的消息。 要存储错误,您可能需要额外的 state,或将其放入货币 state 中。

使用复杂的 state 遵循这种方法将引导您自己编写 Redux。

  1. useReducer (这是 React reducer,不是 Redux)允许使用操作来操作复杂的 state。 即您将能够分别调度SET_CURRENCY动作和SET_RATES动作,并且useReducer将相应地更新 state。 但它没有任何异步代码逻辑(即从服务器获取速率)。 您应该使用自定义挂钩自己编写。

  2. Redux 是处理 state 的最复杂的方法。 它允许使用操作更新 state 的部分内容并处理异步操作。 如果您考虑使用Redux Toolkit之类的库,您将能够从项目中删除大量样板代码并使用复杂的 state 更新逻辑。

根据我的经验, useState适用于简单的 state,例如打开对话框。 所有其他 state 转到 Redux。

另外,我可以提一下表单的 state,它可以使用诸如Reach Hook Forms 之类的库进行操作。 React 钩子表单将在内部保存特定于表单的 state,并为您提供特定于表单的 state,例如错误、触摸、提交计数等。

提供的示例中的第二部分是 state 提供程序部分。 它是通过上下文完成的。 这是意料之中的,因为useState不建议将 state 传递给组件。 Redux 也在使用上下文,但它是由 React-Redux 库为您创建的。 此外,React-Redux 将为您提供有用的工具,如useSelector到 select 仅 state 的一部分。 React 上下文没有任何选择器。 它将为您提供完整的 state,您必须使用useMemo获取 state 的一部分并将其传递给较低级别的组件。 同样,它类似于自己编写 React-Redux 库。

最后一个问题。 提供的代码中没有方法的名称或模式。 一些开发人员刚刚为一个项目发明了它。 从我的角度来看,这种方法没有什么有趣的。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM