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

ReactJS中如何正确将类组件转换为函数组件

错误原因

转换后的代码存在几个核心问题,直接导致报错和功能异常:

  • 给reactstrap的Dropdown组件传入的toggle属性是空字符串,不是合法的函数类型。组件内部点击触发toggle逻辑时,尝试执行这个字符串就会抛出toggle is not a function的错误。
  • 额外绑定的onClick={openModal}逻辑只会把展开状态固定设置为true,完全没有实现原组件「点击切换展开/收起状态」的逻辑,所以下拉菜单会始终保持展开无法关闭。
  • 报错后组件内部状态更新逻辑紊乱,触发无意义的重复重渲染,直接导致页面运行速度下降。
  • 移除了原组件外层的路由包裹、react-redux连接、i18n国际化包裹逻辑,和原类组件的功能不对等,无法读取全局状态、国际化文案和路由实例。
  • 多余引入了Component、useEffect等未使用的依赖,属于无效代码。
等价函数组件实现

下面的代码完全对齐原类组件的逻辑,同时保留了新增的firebase登出跳转逻辑,用React Hooks替代了原有的高阶组件写法,更符合函数组件的开发习惯:

import React, { useState } from "react";
import PropTypes from 'prop-types';
import {
  Dropdown,
  DropdownToggle,
  DropdownMenu,
  DropdownItem,
} from "reactstrap";
import { useHistory } from "react-router-dom";
import { useTranslation } from "react-i18next";
import { useSelector } from "react-redux";
import firebase from "../../../firebase"

function ProfileMenu(){
  const [menuOpen, setMenuOpen] = useState(false);
  const [name] = useState("Admin"); // 后续可替换为接口返回的真实用户名
  const history = useHistory();
  const { t } = useTranslation();
  // 读取redux中存储的Profile状态
  const success = useSelector(state => state.Profile.success);

  // 对齐原组件的下拉菜单切换逻辑
  const toggle = () => {
    setMenuOpen(prevState => !prevState)
  }

  // 登出逻辑
  const handleLogout = () => {
    firebase.auth().signOut().then(() => {
      console.log("logged out")
      history.push("/login");
    }).catch((error) => {
      console.log("logout failed", error)
    });
  }

  return (
    <React.Fragment>
      <Dropdown
        isOpen={menuOpen}
        toggle={toggle}
        className="d-inline-block"
      >
        <DropdownToggle
          className="btn header-item"
          id="page-header-user-dropdown"
          tag="button"
        >
          <span className="d-none d-xl-inline-block ms-1">
            {name}
          </span>
          <i className="mdi mdi-chevron-down d-none d-xl-inline-block" />
        </DropdownToggle>
        <DropdownMenu className="dropdown-menu-end">
          <DropdownItem tag="a" href="/">
            Dashboard
          </DropdownItem>
          <div className="dropdown-divider" />
          <button className="dropdown-item" onClick={handleLogout}>
            <i className="bx bx-power-off font-size-16 align-middle me-1 text-danger" />
            <span>{t("Logout")}</span>
          </button>
        </DropdownMenu>
      </Dropdown>
    </React.Fragment>
  )
}

ProfileMenu.propTypes = {
  success: PropTypes.string
}

export default ProfileMenu
关键改动说明
  • 移除了错误的空字符串toggle传值和固定设置展开状态的onClick事件,传入和原逻辑一致的状态切换函数。
  • 用useTranslation、useSelector、useHistory三个Hooks替代了原有的withTranslation、connect、withRouter高阶组件,代码更简洁。
  • 保留了原组件默认用户名、国际化文案、菜单项结构的所有逻辑,同时兼容新增的firebase登出跳转能力。
  • 清理了所有未使用的导入和冗余的open/close方法,避免无效重渲染。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.30 16:54:21