🥹React Context với TypeScript: Phần 2 - Bối cảnh phức tạp với các thành phần hàm

https://www.carlrippon.com/react-context-with-typescript-p2/

src\App.tsx

import { createContext, useContext, useState, useEffect } from "react";
// Step 1 Thiết lập rõ ràng loại ngữ cảnh
const defaultTheme = "white";
const ThemeContext = createContext<any>(undefined);
// Step 2 Sử dụng ngữ cảnh nâng cao trong nhà cung cấp
export const ThemeProvider = ({ children }: any) => {
  const [theme, setTheme] = useState(defaultTheme);
  useEffect(() => {
    const currentTheme = "lightblue";
    setTheme(currentTheme);
  }, []);
  return (
    <ThemeContext.Provider value={{ theme, setTheme }}>
      {children}
    </ThemeContext.Provider>
  );
};
// Step 3 Thêm tùy chọn để thay đổi chủ đề trong Header thành phần
export const useTheme = () => useContext(ThemeContext);
const Header = () => {
  const { theme, setTheme } = useTheme()!;
  return (
    <div style={{ backgroundColor: theme }}>
      <select value={theme} onChange={e => setTheme(e.currentTarget.value)}>
        <option value="white">White</option>
        <option value="lightblue">Blue</option>
        <option value="lightgreen">Green</option>
      </select>
      <span>Hello!</span>
    </div>
  );
};
function App() {
  return (
    <ThemeProvider>
      <Header />
    </ThemeProvider>
  );
}
export default App;

Đây là bài đăng thứ hai trong loạt bài đăng về ngữ cảnh React với TypeScript. Trong bài đăng trước , chúng tôi đã tạo một ngữ cảnh đơn giản trong đó TypeScript có thể suy ra kiểu của nó.

Trong bài viết này, chúng ta sẽ triển khai một ngữ cảnh phức tạp hơn, trong đó chúng ta cần chỉ định rõ ràng loại ngữ cảnh.

Thiết lập rõ ràng loại ngữ cảnh

Chúng tôi sẽ bổ sung thêm nội dung từ bài đăng trước để người tiêu dùng có thể cập nhật chủ đề.

Trong bài đăng trước, kiểu cho ngữ cảnh được suy ra từ giá trị mặc định, là một giá trị đơn giản string. Kiểu cho ngữ cảnh nâng cao của chúng ta sẽ phức tạp hơn một chút:

type ThemeContextType = {
  theme: string;
  setTheme: (value: string) => void;
};

Vì vậy, sẽ có một themethuộc tính chứa giá trị hiện tại cho chủ đề và một setThemephương thức để cập nhật chủ đề hiện tại.

Hàm Reacts createContextmong đợi chúng ta cung cấp một đối số cho giá trị ngữ cảnh ban đầu. Chúng ta có thể cung cấp một giá trị mặc định cho themethuộc tính, nhưng không hợp lý khi cung cấp một triển khai mặc định cho setThemephương thức. Vì vậy, một cách tiếp cận đơn giản là truyền vào undefinednhư giá trị ban đầu:

const ThemeContext = React.createContext(
  undefined
);

Chúng ta hãy xem kiểu suy ra cho giá trị ngữ cảnh là gì:

Kiểu của giá trị ngữ cảnh được suy ra là undefinedở chế độ nghiêm ngặt hay anykhông.

Vì vậy, ThemeContextkhông được gõ như chúng ta yêu cầu tại thời điểm này. Làm thế nào chúng ta có thể chỉ định rõ ràng loại cho ngữ cảnh khi sử dụng createContext? Vâng, createContextlà một hàm chung. Vì vậy, chúng ta có thể truyền vào loại cho giá trị ngữ cảnh dưới dạng tham số chung:

const context = React.createContext<ContextType>(...)

Do đó, chúng ta có thể nhập ngữ cảnh của mình như sau:

const ThemeContext = React.createContext<
  ThemeContextType | undefined
>(undefined);

Sử dụng ngữ cảnh nâng cao trong nhà cung cấp

Sự thay đổi đối với nhà cung cấp ngữ cảnh, từ bài đăng trước, là giá trị chúng ta cung cấp từ nó. Thay vì một , đơn giản string, giờ đây nó là một đối tượng chứa thuộc themetính và setThemephương thức:

export const ThemeProvider = ({
  children
}: Props) => {
  ...

  return (
    <ThemeContext.Provider value={{ theme, setTheme }}>
      {children}
    </ThemeContext.Provider>
  );
};

Thêm tùy chọn để thay đổi chủ đề trong Headerthành phần

Hook useThemetùy chỉnh vẫn giữ nguyên như trong bài đăng trước. AppThành phần cũng vẫn giữ nguyên.

Tuy nhiên, chúng ta sẽ thay đổi Headerthành phần để người dùng có thể thay đổi chủ đề:

const Header = () => {
  const { theme, setTheme } = useTheme()!;
  return (
    <div style={{ backgroundColor: theme }}>
      <select value={theme} onChange={e => setTheme(e.currentTarget.value)}>
        <option value="white">White</option>
        <option value="lightblue">Blue</option>
        <option value="lightgreen">Green</option>
      </select>
      <span>Hello!</span>
    </div>
  );
};

Chúng tôi giải cấu trúc giá trị chủ đề hiện tại cũng như setThemephương thức từ useThemehook. Lưu ý rằng chúng tôi đã đặt dấu chấm than ( !) sau lệnh gọi useThemehook để báo cho trình biên dịch TypeScript rằng giá trị trả về của nó sẽ không phải là undefined.

Chúng tôi cũng đã thêm một menu thả xuống có các tùy chọn để thay đổi chủ đề thành Trắng , Xanh lamXanh lục . Giá trị của menu thả xuống được đặt thành giá trị chủ đề hiện tại và khi giá trị này thay đổi, nó sẽ gọi phương thức contexts setThemeđể cập nhật giá trị này trong trạng thái được chia sẻ.

Có thể xem toàn bộ nội dung bằng cách nhấp vào liên kết bên dưới. Hãy thử và thay đổi giá trị chủ đề và xem màu nền thay đổi.

Mở triển khai đầy đủ

Kết thúc

Nhìn chung, chúng ta sẽ cần tạo một kiểu cho ngữ cảnh và định nghĩa rõ ràng kiểu khi ngữ cảnh được tạo. Giá trị ban đầu cho ngữ cảnh thường là undefined, do đó kiểu ngữ cảnh thường là kiểu hợp nhất chứa undefined. Chúng ta cần sử dụng toán tử khẳng định không null ( !) khi tham chiếu ngữ cảnh để cho TypeScript biết rằng ngữ cảnh có giá trị.

Trong bài đăng thứ 4 trong loạt bài này, chúng ta sẽ đề cập đến một cách không phải truyền giá trị mặc định cho ngữ cảnh và không phải xử lý nó có thể là undefined. Trước đó, trong bài đăng tiếp theo, chúng ta sẽ tìm hiểu cách sử dụng ngữ cảnh được gõ mạnh với các thành phần lớp.

Last updated

Was this helpful?