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

TypeScript类组件全局状态实现及Hook调用报错解决

问题原因

你遇到的错误是因为React Hook只能在函数组件或自定义Hook中调用,类组件不支持直接使用Hook,这是React Hook的核心规则之一。以下是几种适配类组件的解决方案:


解决办法1:将类组件转为函数组件(推荐)

React官方推荐函数组件+Hook的写法,代码更简洁且符合现代React最佳实践,直接适配你已有的Context实现:

page.tsx 改造后

import { useGlobalState, GlobalStateInterface } from "../../app/GlobalStateProvider";
import { useForm } from "react-hook-form";

const PageComponent = () => {
  const { setState } = useGlobalState();
  const { handleSubmit } = useForm();

  const submitFunction = async (data: Partial<GlobalStateInterface>) => {
    // 设置状态为指定内容
    setState((prev) => ({ ...prev, abcstring: "操作中..." }));
    try {
      // 执行你的业务逻辑(比如文件上传等异步操作)
      // await yourAsyncUploadLogic();
    } finally {
      // 方法结束后重置为null
      setState((prev) => ({ ...prev, abcstring: null }));
    }
  };

  const handleFileChange = (e: React.ChangeEvent<HTMLInputElement>) => {
    // 你的文件处理逻辑
  };

  return (
    <>
      <input
        accept=".csar,.yaml"
        id="file"
        min={1}
        max={1}
        multiple={false}
        type="file"
        name="abc"
        onChange={handleFileChange}
      />
      <label htmlFor="file">
        <form onSubmit={handleSubmit(submitFunction)}>
          <Button
            className={inputUploadButton}
            component="span"
            variant="primary"
            type="submit"
            isSmall
            onClick={(e) => e.stopPropagation()}
          >
            <Tooltip key={`Upload`} content={<div>Upload</div>}>
              <UploadIcon />
            </Tooltip>
          </Button>
        </form>
      </label>
    </>
  );
};

export default PageComponent;

Page2.tsx 改造后

import { useGlobalState } from "../../../app/GlobalStateProvider";

const Page2Component = () => {
  const { state } = useGlobalState();

  return (
    <>
      <ToolbarItem>
        {console.log(state.abcstring)}
        {state.abcstring === "操作中..." ? (
          <Title sizes={'sm'} headingLevel={'h6'}>
            operation in progress...
          </Title>
        ) : null}
      </ToolbarItem>
    </>
  );
};

export default Page2Component;

解决办法2:使用Context.Consumer(保留类组件)

如果不想改造类组件结构,可以直接用GlobalStateContext.Consumer在类组件的render方法中获取上下文:

Page2.tsx 修改后

import React from "react";
import { GlobalStateContext } from "../../../app/GlobalStateProvider";

class ClassName2 extends React.Component {
  render() {
    return (
      <GlobalStateContext.Consumer>
        {({ state }) => (
          <>
            <ToolbarItem>
              {console.log(state.abcstring)}
              {state.abcstring === "操作中..." ? (
                <Title sizes={'sm'} headingLevel={'h6'}>
                  operation in progress...
                </Title>
              ) : null}
            </ToolbarItem>
          </>
        )}
      </GlobalStateContext.Consumer>
    );
  }
}

export default ClassName2;

page.tsx 修改后(拆分表单逻辑为子组件)

import React from "react";
import { GlobalStateContext, GlobalStateInterface } from "../../app/GlobalStateProvider";
import { useForm } from "react-hook-form";

// 抽离表单提交逻辑为函数组件(适配useForm Hook)
const SubmitButton = () => {
  const { handleSubmit } = useForm();
  return (
    <GlobalStateContext.Consumer>
      {({ setState }) => {
        const submitFunction = async (data: Partial<GlobalStateInterface>) => {
          setState((prev) => ({ ...prev, abcstring: "操作中..." }));
          try {
            // 执行业务逻辑
          } finally {
            setState((prev) => ({ ...prev, abcstring: null }));
          }
        };

        return (
          <form onSubmit={handleSubmit(submitFunction)}>
            <Button
              className={inputUploadButton}
              component="span"
              variant="primary"
              type="submit"
              isSmall
              onClick={(e) => e.stopPropagation()}
            >
              <Tooltip key={`Upload`} content={<div>Upload</div>}>
                <UploadIcon />
              </Tooltip>
            </Button>
          </form>
        );
      }}
    </GlobalStateContext.Consumer>
  );
};

export class ClassName extends React.Component {
  handleFileChange = (e: React.ChangeEvent<HTMLInputElement>) => {
    // 文件处理逻辑
  };

  render() {
    return (
      <>
        <input
          accept=".csar,.yaml"
          id="file"
          min={1}
          max={1}
          multiple={false}
          type="file"
          name="abc"
          onChange={this.handleFileChange}
        />
        <label htmlFor="file">
          <SubmitButton />
        </label>
      </>
    );
  }
}

export default ClassName;

解决办法3:基于React-Redux实现(适配你的技术栈)

既然你的应用是基于React-Redux构建的,也可以直接用Redux管理该全局状态,类组件通过connect高阶组件连接store:

1. 定义Redux Action和Reducer

// actions.ts
export const SET_GLOBAL_STATE = 'SET_GLOBAL_STATE';
export const RESET_GLOBAL_STATE = 'RESET_GLOBAL_STATE';

export const setGlobalState = (payload: Partial<GlobalStateInterface>) => ({
  type: SET_GLOBAL_STATE,
  payload,
});

export const resetGlobalState = (keys: string[]) => ({
  type: RESET_GLOBAL_STATE,
  payload: keys,
});

// reducer.ts
import { SET_GLOBAL_STATE, RESET_GLOBAL_STATE } from './actions';

const initialState: Partial<GlobalStateInterface> = {
  abcstring: null,
  xyzstring: null,
};

export const globalReducer = (state = initialState, action: any) => {
  switch (action.type) {
    case SET_GLOBAL_STATE:
      return { ...state, ...action.payload };
    case RESET_GLOBAL_STATE:
      return action.payload.reduce((acc: any, key: string) => {
        acc[key] = null;
        return acc;
      }, { ...state });
    default:
      return state;
  }
};

2. 类组件中使用connect

page.tsx

import React from "react";
import { connect } from "react-redux";
import { setGlobalState, resetGlobalState } from "./actions";
import { useForm } from "react-hook-form";

// 抽离提交逻辑为函数组件
const SubmitButton = ({ setGlobalState, resetGlobalState }) => {
  const { handleSubmit } = useForm();
  const submitFunction = async (data) => {
    setGlobalState({ abcstring: "操作中..." });
    try {
      // 执行业务逻辑
    } finally {
      resetGlobalState(['abcstring']);
    }
  };
  return (
    <form onSubmit={handleSubmit(submitFunction)}>
      {/* 按钮代码 */}
    </form>
  );
};

const mapDispatchToProps = {
  setGlobalState,
  resetGlobalState,
};

const ConnectedSubmitButton = connect(null, mapDispatchToProps)(SubmitButton);

export class ClassName extends React.Component {
  handleFileChange = (e: React.ChangeEvent<HTMLInputElement>) => {
    // 文件处理逻辑
  };

  render() {
    return (
      <>
        <input
          accept=".csar,.yaml"
          id="file"
          min={1}
          max={1}
          multiple={false}
          type="file"
          name="abc"
          onChange={this.handleFileChange}
        />
        <label htmlFor="file">
          <ConnectedSubmitButton />
        </label>
      </>
    );
  }
}

export default ClassName;

Page2.tsx

import React from "react";
import { connect } from "react-redux";

class ClassName2 extends React.Component {
  render() {
    const { abcstring } = this.props;
    return (
      <>
        <ToolbarItem>
          {console.log(abcstring)}
          {abcstring === "操作中..." ? (
            <Title sizes={'sm'} headingLevel={'h6'}>
              operation in progress...
            </Title>
          ) : null}
        </ToolbarItem>
      </>
    );
  }
}

const mapStateToProps = (state) => ({
  abcstring: state.global.abcstring,
});

export default connect(mapStateToProps)(ClassName2);

内容的提问来源于stack exchange,提问作者Dhananjay Gahiwade

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.18 02:35:19