React+TypeScript教程之5 - useContext


由微软推出的TypeScript自从一推出就广受关注,现在无论开发前端React/Vue,还是后端API,很多项目中都广泛接受了TypeScript。下面以如何定义主题为例,介绍如何通过TypeScript使用React中的useContext Hook。

TypeScript
TypeScript

通过useContext来保存用户登录信息

定义用户类型

首先增加文件User.ts:

TypeScript
export type User = {
  userid: string
  email: string
  role: string
}

定义UserContext

然后增加文件UserContext.tsx:

TypeScript
import React, { useState, createContext } from 'react';
import { User } from './User';

type UserContextType = {
  user: User | null
  setUser: React.Dispatch<React.SetStateAction<User | null>>
}

type UserContextProviderProps = {
  children: React.ReactNode
}

export const UserContext = createContext<UserContextType>({} as UserContextType);

export const UserContextProvider = ({ children }: UserContextProviderProps) => {
  const [user, setUser] = useState<User | null>(null)
  
  return (
    <UserContext.Provider value={{ user, setUser }}>
      {children}
    </UserContext.Provider>
  )
}

使用UserContext的组件

增加文件Header.tsx:

TypeScript
import { useContext } from 'react';
import { UserContext } from './UserContext';

export default function Header() {
  const userContext = useContext(UserContext);

  const handleLogin = () => {
    userContext.setUser({
      userid: '9901',
      email: '[email protected]',
      role: 'admin'
    })
  }
  const handleLogout = () => {
    userContext.setUser(null)
  }

  return <div>
    {userContext.user? (
      <>
        {userContext.user.userid} /{userContext.user.email} / {userContext.user.role}
        <button onClick={handleLogout}>Logout</button>
      </>
    ):(
      <button onClick={handleLogin}>Login</button>
    )}
  </div>;
}

在App.tsx中调用

TypeScript
import "./App.css";
import { UserContextProvider } from "./components/usecontext/UserContext";
import Header from "./components/usecontext/Header";

function App() {
  return (
    <div className="App">
      <UserContextProvider>
        <Header />
      </UserContextProvider>
    </div>
  );
}

export default App;

通过useContext来使用不同的theme

定义theme

添加文件theme.ts,这个文件的作用就是定义主题相关的样式设定:

TypeScript
export const theme = {
  primary: {
    light: '#757ce8',
    main: '#3f50b5',
    dark: '#002884',
    contrastText: '#fff',
  },
  secondary: {
    light: '#ff7961',
    main: '#f44336',
    dark: '#ba000d',
    contrastText: '#000',
  },
}

定义ThemeContext

增加文件ThemeContext.tsx。这个文件的作用就是将子组件包裹在ThemeProvider中,从而将样式传递给子组件。

TypeScript
import { createContext } from "react";
import { theme } from "./theme";

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

export const ThemeContext = createContext(theme);

export const ThemeContextProvider = ({
  children,
}: ThemeContextProviderProps) => {
  return <ThemeContext.Provider value={theme}>{children}</ThemeContext.Provider>;
};

定义使用theme的组件

添加文件Container.tsx:

TypeScript
import { useContext } from "react";
import { ThemeContext } from "./ThemeContext";

export default function Container() {
  const theme = useContext(ThemeContext);

  return (
    <>
      <button
        style={{
          backgroundColor: theme.primary.main,
          color: theme.primary.contrastText,
        }}
      >
        Primary
      </button>
      <br />
      <button
        style={{
          backgroundColor: theme.secondary.main,
          color: theme.secondary.contrastText,
        }}
      >
        Secondary
      </button>
    </>
  );
}

在Container父组件中需要做的工作

更新App.tsx:

TypeScript
import './App.css';
import { ThemeContextProvider } from './components/usecontext/ThemeContext';
import Container from './components/usecontext/Container';

function App() {
  return (
    <div className="App">
      <ThemeContextProvider>
        <Container/>
      </ThemeContextProvider>
    </div>
  );
}

export default App;

文章作者: 逻思
版权声明: 本博客所有文章除特別声明外,均采用 CC BY-NC-ND 4.0 许可协议。转载请注明来源 逻思 !