我总是使用功能组件,因为它们给了我更多的灵活性,我可以使用钩子。我有一个使用类组件编码的下拉菜单功能。现在我需要将其转换为功能组件,因为我需要为一些菜单按钮做一些后端工作,例如注销和名称等。
我试图转换它我自己,但它总是保持模态打开,给我一个错误,读取" this.props.toggle is not a function at Dropdown.toggle"
,它减慢了我的网站难以置信。
如何使下面的代码等同于一个功能组件?
类组件:
import React, { Component } from "react";
import PropTypes from 'prop-types';
import {
Dropdown,
DropdownToggle,
DropdownMenu,
DropdownItem,
} from "reactstrap";
import { withRouter, Link } from "react-router-dom";
//i18n
import { withTranslation } from "react-i18next";
import { connect } from "react-redux";
class ProfileMenu extends Component {
constructor(props) {
super(props)
this.state = {
menu: false,
name: "Admin",
}
this.toggle = this.toggle.bind(this)
}
toggle() {
this.setState(prevState => ({
menu: !prevState.menu,
}))
}
render() {
return (
<React.Fragment>
<Dropdown
isOpen={this.state.menu}
toggle={this.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">
{this.state.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" />
<Link to="/logout" className="dropdown-item">
<i className="bx bx-power-off font-size-16 align-middle me-1 text-danger" />
<span>{this.props.t("Logout")}</span>
</Link>
</DropdownMenu>
</Dropdown>
</React.Fragment>
)
}
}
ProfileMenu.propTypes = {
t: PropTypes.any,
success: PropTypes.string
}
const mapStateToProps = state => {
const { success } = state.Profile
return { success }
}
export default withRouter(
connect(mapStateToProps, {})(withTranslation()(ProfileMenu))
)
下面的代码是我如何尝试转换它
import React, { Component, useState, useEffect } from "react";
import PropTypes from 'prop-types';
import {
Dropdown,
DropdownToggle,
DropdownMenu,
DropdownItem,
} from "reactstrap";
import { withRouter, Link, useHistory } from "react-router-dom";
import firebase from "../../../firebase"
function ProfileMenu(){
const [isOpen, setIsOpen] = useState(false);
const history = useHistory();
const logout = () => {
firebase.auth().signOut().then(function() {
console.log("logged out")
history.push("/login");
}).catch(function(error) {
// An error happened.
console.log("didnt logout")
});
}
const openModal = () => {
setIsOpen(true);
};
const closeModal = () => {
setIsOpen(false);
};
return (
<React.Fragment>
<Dropdown
isOpen={isOpen}
onClick={openModal}
toggle={""}
className="d-inline-block"
>
<DropdownToggle
// onClick={openModal}
className="btn header-item"
id="page-header-user-dropdown"
tag="button"
>
<span className="d-none d-xl-inline-block ms-1">
{/* {this.state.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={logout}>
<i className="bx bx-power-off font-size-16 align-middle me-1 text-danger" />
<span>Logout</span>
</button>
</DropdownMenu>
</Dropdown>
</React.Fragment>
)
}
export default ProfileMenu
const ProfileMenu = (props) => {
const [name, setName] = useState('aaa'); // define and initialize name state
....
let myName = name; // call name state
....
let toggle = props.toggle; //call toggle props
}
我希望这对你有帮助。谢谢。你需要传递toggle作为函数,而不是传递字符串,也可以直接切换状态值,它将使组件重新渲染,尝试下面的代码,让我知道这是否有帮助。
为了更好的可见性,我删除了类名,使代码看起来干净。
您也可以使用useContext
来代替redux。
import React, { useState } from "react";
import { Dropdown, DropdownToggle, DropdownMenu, DropdownItem } from "reactstrap";
import { withRouter, useHistory } from "react-router-dom";
import firebase from "../../../firebase";
type Prop = {
name: string;
};
const ProfileMenu: React.FC<Prop> = ({ name }) => {
const [menu, setMenu] = useState(false);
const history = useHistory();
const logout = () => {
firebase
.auth()
.signOut()
.then(function () {
history.push("/login");
})
.catch(function (error) {
console.log("didnt logout");
});
};
return (
<Dropdown isOpen={menu} toggle={() => setMenu(!menu)} >
<DropdownToggle >
<span >{name}</span>
<i className="mdi mdi-chevron-down d-none d-xl-inline-block" />
</DropdownToggle>
<DropdownMenu >
<DropdownItem tag="a" href="/">
Dashboard
</DropdownItem>
<div className="dropdown-divider" />
<button onClick={logout}>
<i className="bx bx-power-off font-size-16 align-middle me-1 text-danger" />
<span>Logout</span>
</button>
</DropdownMenu>
</Dropdown>
);
};
export default withRouter(ProfileMenu);