useContext 上的 TypeScript

Bar*_*yli 0 javascript typescript react-context createcontext

我正在关注 youtube 上的 React 教程,我正在尝试将项目从 JavaScript 转换为 TypeScript,但我在 useContext 方面遇到了很多麻烦,如果有人在这里帮助我,我将不胜感激。如果您想知道这里的教程是教程

    import React, {createContext, useContext, useState } from 'react';
    
    const StateContext = createContext();
    
    export const ContextProvider = ({ children }) => {
        const [activeMenu, setActiveMenu] = useState(true);
    
        return (
            <StateContext.Provider value={{activeMenu, setActiveMenu}}>
                {children}
            </StateContext.Provider>
        )
    }
    
    export const useStateContext = () => useContext(StateContext)
Run Code Online (Sandbox Code Playgroud)

Spy*_*ias 5

我在野外见过 3 个选项。

选项1

这个选项有点烦人,因为 StateContext 值的类型可以是null | StateContextType. 但在您提供的代码中,它只会null在创建时出现,并且在提供程序内不为 null。无论如何,无论你在哪里使用,useContext你都必须警惕null

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

type StateContextType = {
  activeMenu: boolean;
  setActiveMenu: React.Dispatch<React.SetStateAction<boolean>>;
};

export const StateContext = createContext<null | StateContextType>(null);

type ContextProviderProps = {
  children: React.ReactNode;
};

export const ContextProvider = ({ children }: ContextProviderProps) => {
  const [activeMenu, setActiveMenu] = useState(true);
  const value = {
    activeMenu,
    setActiveMenu,
  };

  return (
    <StateContext.Provider value={value}>{children}</StateContext.Provider>
  );
};
Run Code Online (Sandbox Code Playgroud)

选项2

使用此选项,您可以将 StateContext 值类型转换为 StateContextType。这意味着 StateContext 的值被假定为 StateContextType。唯一的缺点是,null在 StateContext.Provider 中提供值之前,StateContext 的值在创建时只存在很短的一段时间。

但是,它相对安全,因为您立即在提供程序中传递一个值。

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

type StateContextType = {
  activeMenu: boolean;
  setActiveMenu: React.Dispatch<React.SetStateAction<boolean>>;
};

export const StateContext = createContext<StateContextType>(
  null as unknown as StateContextType,
);

type ContextProviderProps = {
  children: React.ReactNode;
};

export const ContextProvider = ({ children }: ContextProviderProps) => {
  const [activeMenu, setActiveMenu] = useState(true);
  const value = {
    activeMenu,
    setActiveMenu,
  };

  return (
    <StateContext.Provider value={value}>{children}</StateContext.Provider>
  );
};
Run Code Online (Sandbox Code Playgroud)

选项3

这要归功于 Steve Kinney 的React 和 TypeScript 前端大师课程。

import React, { useState } from 'react';

export function createContext<T>() {
  const context = React.createContext<T | undefined>(undefined);

  const useContext = () => {
    const value = React.useContext(context);
    if (value === undefined) {
      throw new Error(
        `useContext must be used inside a Provider with a value that's not undefined`,
      );
    }
    return value;
  };
  return [useContext, context.Provider] as const;
}

type StateContextType = {
  activeMenu: boolean;
  setActiveMenu: React.Dispatch<React.SetStateAction<boolean>>;
};

export const [useContext, Provider] = createContext<StateContextType>();

type ContextProviderProps = {
  children: React.ReactNode;
};

export const ContextProvider = ({ children }: ContextProviderProps) => {
  const [activeMenu, setActiveMenu] = useState(true);
  const value = {
    activeMenu,
    setActiveMenu,
  };

  return <Provider value={value}>{children}</Provider>;
};

const Component = () => {
  // usage inside component
  const context = useContext();
  return <div></div>;
};

export const App = () => {
  return (
    <ContextProvider>
      <Component />
    </ContextProvider>
  );
};
Run Code Online (Sandbox Code Playgroud)