反应useContext()的性能,自定义钩子内的useContext

时间:2019-09-23 18:26:21

标签: javascript reactjs rendering react-hooks react-context

我使用了React Hooks的结构。它基于全局Context,其中包含减速器的组合(如Redux中所示)。 另外,我广泛使用custom hooks来分隔逻辑。 我有一个包含异步API请求的钩子,它变得非常繁琐,并且我有机会将这个钩子的几乎每个功能拆分为其他钩子,但是每个这些函数都使用全局上下文(更确切地说,是从useReducer()调度)。

问题:

  1. 可以在每个需要它的钩子中使用useContext()吗?
  2. 例如,如果我创建10个在内部使用useContext()并在组件中使用它们的自定义钩子,它将如何影响性能。

示例:

providers / Store.js

import React, { createContext, useReducer } from 'react';

export const StoreContext = createContext();

export const StoreProvider = ({ children }) => {
  /**
   * Store that contains combined reducers.
   */
  const store = useReducer(rootReducer, initialState);

  return (
    <StoreContext.Provider value={store}>{children}</StoreContext.Provider>
  );
};

hooks / useStore.js

import { useContext } from 'react';
import { StoreContext } from '../providers';

export const useStore = () => useContext(StoreContext);

hooks / useFoo.js

import { useCallback } from 'react';
import { useStore } from './useStore';

export const useFoo = () => {
  const [, dispatch] = useStore();

  const doFoo = useCallback(
    async params => {
      dispatch(actions.request());

      try {
        const res = await SomeService.getSomething(params);
        dispatch(actions.add(res));
        dispatch(actions.success());
      } catch (error) {
        dispatch(actions.failure());
      }
    },
    [dispatch]
  );

  return { doFoo };
};

hooks / useBar.js

import { useCallback } from 'react';
import { useStore } from './useStore';

export const useBar = () => {
  const [, dispatch] = useStore();

  const doBar = useCallback(
    async params => {
      dispatch(actions.request());

      try {
        const res = await SomeService.getSomething(params);
        dispatch(actions.success());
        dispatch(actions.add(res));
      } catch (error) {
        dispatch(actions.failure());
      }
    },
    [dispatch]
  );

  return { doBar };
};

hooks / useNext.js

...
import { useStore } from './useStore';

export const useNext = () => {
  const [, dispatch] = useStore();

  ...
};

components / SomeComponent.js

const SomeComponent = () => {
  // use context
  const [store, dispatch] = useStore();

  // and here is the context
  const { doFoo } = useFoo();

  // and here
  const { doBar } = useBar();

  // and here
  useNext();

  return (
    <>
      <Button onClick={doFoo}>Foo</Button>
      <Button onClick={doBar}>Bar</Button>
      // the flag is also available in another component
      {store.isLoading && <Spin />}
    </>
  )
}

1 个答案:

答案 0 :(得分:0)

在内部,钩子可以引用组件拥有的状态队列。 (Under the hood of React’s hooks system - Eytan Manor

useContext仅用于引用相对上下文提供者的全局状态。就您而言,useContext几乎没有开销。