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
相关产品推荐
相关产品推荐

