如何将类组件转换为ReactJ中的功能组件
我总是使用功能性组件,因为它们可以使我更加灵活性,并且可以与它们一起使用钩子。我有一个使用类组件编码的下拉菜单功能。现在,我需要将其转换为功能组件,因为我需要为某些菜单按钮(例如注销和名称等)进行一些后端工作。
我试图将其转换为自己,但结束时总是保持模态开放,并给我一个错误,读取“ this.props.toggle并不是下拉doggle.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
I always work with functional components as they give me more flexibility and i can use hooks with them. I have a drop down menu functionality that is coded using the class component. Now i need to convert this to a functional component as i need to do some backend work for some of the menu buttons, such as logout and name and so on.
I tried to convert it my self but it ended with always keeping to Modal open and giving me an error that reads " this.props.toggle is not a function at Dropdown.toggle"
and it slowed down my website incredibly.
How can i make the below code equivalent to a functional component?
Class Component:
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))
)
Below code is how i tried to convert it
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
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
我希望这对您有帮助。谢谢。
I hope this will be helpful for you. Thanks.
您需要将切换作为功能传递,而是传递字符串,也可以直接切换状态值,它将使组件重新渲染,尝试以下代码,让我知道这是否有帮助。
为了更好的可见性,我正在删除类名称,因此代码看起来很干净。
您还可以使用
USECONTEXT
而不是使用Redux。You need to pass the toggle as function, you are instead passing string, also you can directly toggle state value, it will make the component re-render, try the following code and let me know if this helps.
Just for better visibility I am removing the class names, so that code looks clean.
You can also use the
useContext
instead of using redux.