You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在React Hook中正确使用服务类解决TypeError报错

报错根因

抛出TypeError: Cannot read property 'exampleParams' of undefined是典型的类方法this上下文丢失问题:
你在Hook中直接返回checkExamples.isPresent的方法引用,脱离了checkExamples实例上下文。当外部调用这个返回的方法时,严格模式下类方法内部的this会指向undefined,自然无法读取实例上的exampleParams属性。
另外原实现还有一个性能问题:每次Hook所在组件重渲染,都会新建一个ExampleService实例,会产生不必要的开销。

修复方案

以下三种方案任选其一即可:

方案1:返回方法时绑定实例上下文

不需要修改原有服务类代码,在返回方法时通过bind固定this指向,同时用useMemo缓存服务实例避免重复创建:

import { ExampleService } from '../somewhere/example-service';
import { useContext, useMemo } from 'react';
import { ExampleContext } from '../contexts/example-context';

export const useExample = () => {
  const { currentExamples } = useContext(ExampleContext);
  const checkExamples = useMemo(
    () => new ExampleService(currentExamples),
    [currentExamples]
  );

  return {
    isPresent: checkExamples.isPresent.bind(checkExamples),
    getAll: checkExamples.getAll.bind(checkExamples),
    setExamples: checkExamples.setExamples.bind(checkExamples)
  };
};

方案2:修改服务类方法为箭头函数

从类定义层面解决this绑定问题,箭头函数会继承定义时的上下文,不会出现this丢失:

export class ExampleService {
  constructor(private exampleParams: string[]) {}

  isPresent = (exampleName: string): boolean => {
    return this.exampleParams.includes(exampleName);
  };

  getAll = (): string[] => {
    return this.exampleParams;
  };

  setExamples = (exampleParams: string[]): void => {
    this.exampleParams = exampleParams;
  };
}

类修改完成后,Hook侧不需要额外bind,配合useMemo缓存实例即可正常使用:

export const useExample = () => {
  const { currentExamples } = useContext(ExampleContext);
  const checkExamples = useMemo(
    () => new ExampleService(currentExamples),
    [currentExamples]
  );

  return {
    isPresent: checkExamples.isPresent,
    getAll: checkExamples.getAll,
    setExamples: checkExamples.setExamples
  };
};

方案3:返回包裹的箭头函数

不需要修改类定义,在Hook侧用箭头函数包裹实例方法调用,明确调用主体,也不会出现this丢失问题:

export const useExample = () => {
  const { currentExamples } = useContext(ExampleContext);
  const checkExamples = useMemo(
    () => new ExampleService(currentExamples),
    [currentExamples]
  );

  return {
    isPresent: (exampleName: string) => checkExamples.isPresent(exampleName),
    getAll: () => checkExamples.getAll(),
    setExamples: (params: string[]) => checkExamples.setExamples(params)
  };
};

注意:原代码返回值用数组包裹方法,实际使用时解构需要严格对应顺序,改成对象返回的方式使用成本更低,也不容易出现顺序对应错误的问题。

内容的提问来源于stack exchange,提问作者Shlomi Zadok

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.28 05:06:05