如何将类组件转换为ReactJ中的功能组件

发布于 2025-02-06 21:38:45 字数 4367 浏览 2 评论 0原文

我总是使用功能性组件,因为它们可以使我更加灵活性,并且可以与它们一起使用钩子。我有一个使用类组件编码的下拉菜单功能。现在,我需要将其转换为功能组件,因为我需要为某些菜单按钮(例如注销和名称等)进行一些后端工作。

我试图将其转换为自己,但结束时总是保持模态开放,并给我一个错误,读取“ 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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

凉墨 2025-02-13 21:38:45
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

}

我希望这对您有帮助。谢谢。

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

}

I hope this will be helpful for you. Thanks.

乱了心跳 2025-02-13 21:38:45

您需要将切换作为功能传递,而是传递字符串,也可以直接切换状态值,它将使组件重新渲染,尝试以下代码,让我知道这是否有帮助。

为了更好的可见性,我正在删除类名称,因此代码看起来很干净。

您还可以使用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);


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.

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);


~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文