属性 类型 "props | undefined" 上不存在进程

Property processes does not exist on type "props | undefined"

我正在学习 React Context 并且我正在使用我构建的项目作为测试。

创建上下文后,我试图在显示以下错误的组件上使用它:属性“processes”在类型“Props | undefined”上不存在。但它确实存在于界面上,它也在 ProcessContext.tsx 上。

interface.tsx

export default interface Props {
  children?: any;
  processes?: Array<string>;
  setProcesses?: (active: any) => void;
  updating?: boolean;
  setUpdating?: (active: boolean) => void;
  getProcesses?: () => void;
}

ProcessContext.tsx

import { createContext, FC, useState } from "react";
import { collection, getDocs } from "firebase/firestore";
import { db } from "../firebase";
import Props from "../Interface/Api";

const ProcessContext = createContext<Props | undefined>(undefined);
export const ProcessProvider: FC<Props> = ({ children }) => {
  const [processes, setProcesses] = useState<Array<any>>([]);
  const [updating, setUpdating] = useState<boolean>(false);

  const getProcesses = async () => {
    const processCollectionRef = collection(db, "processes");
    const data = await getDocs(processCollectionRef);
    setProcesses(data.docs.map((doc) => ({ ...doc.data(), id: doc.id })));
  };

  return (
    <ProcessContext.Provider
      value={{ processes, setProcesses, updating, setUpdating, getProcesses }}
    >
      {children}
    </ProcessContext.Provider>
  );
};

export default ProcessContext;

CourseTable.tsx

import React, { FC, Fragment, useState, useContext, useEffect } from "react";
import CheckIcon from "@mui/icons-material/Check";
import {
  Modal,
  Table,
  TableBody,
  TableCell,
  TableContainer,
  TableHead,
  TableRow,
} from "@mui/material";
import ModalData from "./ModalData";
import ProcessContext from "../context/ProcessContext";
import Props from "../Interface/Api";

const CourseTable: FC = () => {
  const { processes, updating, getProcesses } = useContext(ProcessContext);
  const [open, setOpen] = useState(false);
  const handleOpen = () => setOpen(true);
  const handleClose = () => setOpen(false);

  useEffect(() => {
    getProcesses();
  }, [updating]);
}

问题是当您创建上下文时,您指定它的类型可以是 undefinedcreateContext() 当组件在其祖先中没有提供程序的情况下调用它时,上下文采用默认值。您也将此值设置为 undefined

const ProcessContext = createContext<Props | undefined>(undefined);

这是一种完全有效的上下文初始化方法,如果组件的祖先中没有提供程序,那么上下文可以是 undefined 是有道理的。组件不“知道”是否有提供者作为祖先为其尝试使用的上下文提供值。

但是,如果您的上下文是 undefined,那么表达式

const { processes } = useContext(ProcessContext);

导致 javascript 错误,这是 Typescript 警告您的内容。如果您从没有访问提供程序的组件调用上下文,则此警告只会变成 javascript 错误。仍然很高兴 Typescript 可以在它变成错误之前捕捉到它。

有两种方法可以解决这个问题:

  1. 当你调用useContext()
  2. 时处理上下文值为undefined的可能性
  3. 使用 undefined
  4. 以外的默认值初始化您的上下文

对于 1. 代码可能如下:

const processContextValue = useContext(ProcessContext);
if (processContextValue) {
  const { processes, ... } = processContextValue;
  // Do stuff with processes
}

该代码只是选项之一,处理未定义值的方法有很多。您可以在 typescript docs.

中检查 narrowing 类型的概念(从联合中找出类型)

对于 2. 一个常见的做法是用合理的默认值(也可以是未定义的)初始化上下文对象中的每个成员(在您的 Props 接口中指定的所有项目)。

const ProcessContext = createContext<Props>({
  children: undefined,
  processes: [], // You can always use `undefined`, but you can also use a default value like an empty array
  setProcesses: undefined,
  updating: false,
  setUpdating: undefined, // Functions could be `undefined`
  getProcesses: () => null, // or a default function that satisfies the type
});

我还注意到您将每个字段都设为可选,没有必要仅仅因为您使用 Context,如果 undefined 是一个可能的值,它们就必须是可选的。