在 ReactJS 上下文中使用对象 - 对象中的方法导致 属性 'myMethod' 在类型 'unknown' 上不存在

Using object in ReactJS Context - method in object causes Property 'myMethod' does not exist on type 'unknown'

我第一次尝试使用上下文,我有一个创建上下文的 Reactjs 库,然后在主应用程序中更新上下文并作为 app.js 中的上下文提供程序传递。

我的图书馆里有以下这些:

import * as React from "react";

export const MyContext = React.createContext(null);

export const MyContextProvider = MyContext.Provider;
export const MyContextConsumer = MyContext.Consumer;

export class MyClass
{
    constructor()
    {
        ....
    }

    ...

    myMethod(param1, param2 = null)
    {
        ...
    }

然后在我的主项目里面app.tsx我有以下内容:

const my_class = new MyClass();
my_class.initialise("param1", "param2", "param3");

<MyContextProvider value={my_class}>
          <ErrorBoundary>
              <BrowserRouter>
                  <Routes>
                      <Route index element={<Home />} />
                      <Route path='/blog' element={<BlogHome />} />
                      <Route path='/blog/:slug' element={<BlogPost />} />
                      <Route path='*' element={<NotFound />} />
                  </Routes>
              </BrowserRouter>
          </ErrorBoundary>
      </MyContextProvider>

然后在我的子组件中,在这种情况下 NotFound 组件,然后我执行以下操作:

const my_class = useContext(MyContext);
console.log("My class context", my_class);
my_class.myMethod(err, "Low");

编译失败,因为方法 myMethod 抛出错误 Property 'myMethod' does not exist on type 'unknown'

当我删除对 myMethod 的调用并只打印 my_class 时,该对象具有传递给构造函数的所有内容,我可以看到其中的方法,尽管它在 [[Prototype ]] 对象,但不确定这是否符合预期,或者我是否应该以某种方式引用它来访问方法调用。

很难说没有 mcve,但我猜你没有正确使用 MyContext。也就是说,通常情况下,上下文将是一个具有属性和方法的对象:

value: {
  firstName: "Bob", // value from state
  lastName: "Smith", // value from state
  changeFirstName: () => {}, // some sort of state updater
  changeLastName: () => {}, // some sort of state updater
  otherCallback: () => {}, // some sort of callback that affects the UI
  ...etc
}

以上内容遵循更标准的方法,因为值来自状态(来自共享状态对象或分离的 useState 值)和一些包含状态的方法 setters 来更新这些值因此。由于您使用的是 useContext 挂钩,因此函数式编程 (FP) 方法会更有意义;但是,您似乎正在尝试将 OOP(普通 class)与 FP 混合使用。除非绝对需要使用 class,否则我建议使用上面的平面对象方法。

就是说,这是在上下文中使用普通 class 的方法...

工作演示:

理想情况下,您需要使用创建上下文的 class 字段初始化上下文:

import { createContext, useContext } from "react";
import User, { IUser } from "./User";

const user = new User("Bob", "Smith");
export const UserContext = createContext<IUser>(user);

export const useUserContext = () => useContext(UserContext);

然后,导入 UserContext 上下文和 useUserContext 挂钩,并在您的应用程序的顶层使用它们:

import { UserContext, useUserContext } from "./UserContext";

const App = (): ReactElement => (
  <UserContext.Provider value={useUserContext()}>
    {...}
  </UserContext.Provider>
);

export default App;

在子组件中,您可以导入 useUserContext 挂钩并相应地使用其 return 值的 fields/properties:

import { useUserContext } from "./UserContext";
import { ReactElement } from "react";

const Main = (): ReactElement => {
  const user = useUserContext();

  return (
    <main className="main">
      <h1>User Context</h1>
      <h2 className="user">
        <strong>First Name:</strong> {user.firstName}
      </h2>
      <h2 className="user">
        <strong>Last Name:</strong> {user.lastName}
      </h2>
      <h2 className="user">
        <strong>Combined Name:</strong> {user.combinedName()}
      </h2>
    </main>
  );
};

export default Main;

但是这种方法有问题!

您要 运行 解决的问题是,如果您计划 manipulating/updating class 中的字段... React 不会 处理可变字段的变化。因此,如果您更改 class 字段,该更改 不会 重新呈现应用程序(如上面的演示所示)。

相反,您需要利用 state(来自 React Component class 或钩子)和某种 操纵状态 的回调(调用 this.setState({...}) 的回调或调用 useState 状态 setter 的回调)。因此,在上下文中使用普通的 class 确实没有多大意义,因为它只能是静态的 stored/utilized.

这是一个如何在上下文中使用状态的示例:

我认为这个问题是由我的主项目中的打字稿问题引起的。

我有 const my_class = useContext(MyContext) 的地方我必须设置 my_class 的类型 const my_class : MyContext = useContext(MyContext) 解决了问题