ホームページ  >  記事  >  ウェブフロントエンド  >  完全に型指定された簡単な React Context API の例

完全に型指定された簡単な React Context API の例

Linda Hamilton
Linda Hamiltonオリジナル
2024-10-28 07:10:30904ブラウズ

Fully Typed, Easy React Context API Example

コンテキスト タイプのベビーシッターを不要にするコツは簡単です!

コンテキスト API を使用する場合、1 つの問題はその型の子守りです。

もう 1 つは、必要なときに使用するために複数のインポートを使用する必要があることです。

この例では、両方の問題を解決し、React Context API をすばやく簡単に使用できるようにします。

コピー&ペーストの例

コピーして貼り付け、すべての「例」を必要な名前に置き換えるだけで準備完了です。

(その後、完全にコメントされたバージョンが公開されます。)

import {
  createContext,
  useCallback,
  useContext,
  useDeferredValue,
  useMemo,
  useState,
} from 'react';

function useContextValue(init: number = 0) {
  const [state, setState] = useState(init);

  const doubleValue = state * 2;
  const defferedStringValue = useDeferredValue(state.toString());

  const reset = useCallback(() => {
    setState(init);
  }, []);

  const value = useMemo(
    () => ({
      state,
      doubleValue,
      defferedStringValue,
      reset,
    }),
    [
      state,
      doubleValue,
      defferedStringValue,
      reset,
    ],
  );

  return value;
}

type ExampleContext = ReturnType<typeof useContextValue>;

const Context = createContext<ExampleContext>(null!);

Context.displayName = 'ExampleContext';

export function ExampleContextProvider({
  children,
  initValue = 0,
}: {
  children: React.ReactNode;
  initValue?: number;
}) {
  const value = useContextValue(initValue);
  return <Context.Provider value={value}>{children}</Context.Provider>;
}

export function useExample() {
  const value = useContext(Context);

  if (!value) {
    throw new Error('useExample must be used within a ExampleContextProvider');
  }

  return value;
}

コメント付きバージョン

import {
  createContext,
  useCallback,
  useContext,
  useDeferredValue,
  useMemo,
  useState,
} from 'react';

/**
 * We create a custom hook that will have everything
 * that would usually be in the context main function
 *
 * this way, we can use the value it returns to infer the
 * type of the context
 */
function useContextValue(init: number = 0) {
  // do whatever you want inside

  const [state, setState] = useState(init);

  const doubleValue = state * 2;
  const defferedStringValue = useDeferredValue(state.toString());

  // remember to memoize functions
  const reset = useCallback(() => {
    setState(init);
  }, []);

  // and also memoize the final value
  const value = useMemo(
    () => ({
      state,
      doubleValue,
      defferedStringValue,
      reset,
    }),
    [
      state,
      doubleValue,
      defferedStringValue,
      reset,
    ],
  );

  return value;
}

/**
 * Since we can infer from the hook,
 * no need to create the context type by hand
 */
type ExampleContext = ReturnType<typeof useContextValue>;

const Context = createContext<ExampleContext>(null!);

Context.displayName = 'ExampleContext';

export function ExampleContextProvider({
  children,
  /**
   * this is optional, but it's always a good to remember
   * that the context is still a react component
   * and can receive values other than just the children
   */
  initValue = 0,
}: {
  children: React.ReactNode;
  initValue?: number;
}) {
  const value = useContextValue(initValue);
  return <Context.Provider value={value}>{children}</Context.Provider>;
}

/**
 * We also export a hook that will use the context
 *
 * this way, we can use it in other components
 * by importing just this one hook
 */
export function useExample() {
  const value = useContext(Context);

  /**
   * this will throw an error if the context
   * is not used within the provider
   *
   * this also avoid the context being "undefined"
   */
  if (!value) {
    throw new Error('useExample must be used within a ExampleProvider');
  }

  return value;
}

最後の言葉

それだけです。 Context API は必要以上に簡単で、より高度に機能していますが、使用する必要がある場合には強力なツールです。

React Context API は Redux (または他の状態マネージャー) ではないので、アプリケーションの状態全体をそこに押し込むべきではないことを覚えておいてください。

それは可能ですが、不必要な問題が発生する可能性があります。

これは React で書かれています

19 を念頭に置いて、新しいコンパイラーが登場すると、暗記と不必要なレンダリングが問題を引き起こすことはなくなるかもしれません。

以上が完全に型指定された簡単な React Context API の例の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。