【问题标题】:How to convert a React Functional Component that uses hooks to a class?如何将使用钩子的 React 功能组件转换为类?
【发布时间】:2019-12-30 15:40:04
【问题描述】:

在尝试将 React 功能组件转换为类时,我遇到了一些障碍。这是我的功能组件代码

import * as React from 'react';
import { withStyles } from '@material-ui/core/styles';
import Drawer from '@material-ui/core/Drawer';
import List from '@material-ui/core/List';
import Divider from '@material-ui/core/Divider';
import ListItem from '@material-ui/core/ListItem';
import ListItemIcon from '@material-ui/core/ListItemIcon';
import ListItemText from '@material-ui/core/ListItemText';
import DashboardIcon from '@material-ui/icons/Dashboard';
import BarChartIcon from '@material-ui/icons/BarChart';
import AssignmentIndIcon from '@material-ui/icons/AssignmentInd';
import { Link } from 'react-router-dom';
import './drawer.scss';
import { useEffect } from 'react';

const drawerWidth = 87;
const styles = {
  root: {
    display: 'flex'
  },
  appBar: {
    zIndex: 2000
  },
  drawer: {
    width: drawerWidth,
    flexShrink: 0
  },
  drawerPaper: {
    width: drawerWidth
  },
  content: {
    flexGrow: 1,
    padding: 3
  }
};

interface Props {
  classes: any;
}

const ClippedDrawer = (props: Props) => {
  const [selectedIndex, setSelectedIndex] = React.useState(-1);

  useEffect(() => {
    const path: string = window.location.pathname;

    switch (path) {
      case '/':
        setSelectedIndex(1);
        break;
      default:
        setSelectedIndex(1);
        break;
    }
  }, []);

  const { classes } = props;

  const handleClickDashboard = (
    event:
      | React.MouseEvent<HTMLLIElement>
      | React.MouseEvent<HTMLAnchorElement>
      | React.MouseEvent<HTMLDivElement>,
    index: number = 0
  ) => {
    setSelectedIndex(index);
  };

  return (
    <div className={classes.root}>
      <Drawer
        className={classes.drawer}
        variant='permanent'
        classes={{
          paper: classes.drawerPaper
        }}
      >
        <div className={classes.toolbar} />
        <List>
          <Link to={'/'}>
            <ListItem
              button={true}
              selected={selectedIndex === 0}
              onClick={handleClickDashboard}
            >
              <ListItemIcon>
                <DashboardIcon />
              </ListItemIcon>
              <ListItemText primary='Dashboard' />
            </ListItem>
          </Link>
          <Divider />
          <Link to={'/'}>
            <ListItem button={true} selected={selectedIndex === 2}>
              <ListItemIcon>
                <BarChartIcon />
              </ListItemIcon>
              <ListItemText primary='Scenario Analysis' />
            </ListItem>
          </Link>
          <Divider />
          <Link to={'/'}>
            <ListItem button={true} selected={selectedIndex === 3}>
              <ListItemIcon>
                <AssignmentIndIcon />
              </ListItemIcon>
              <ListItemText primary='Admin' />
            </ListItem>
          </Link>
        </List>
        <div className='branding'>
          <p>Powered by</p>
          <div className='logo' />
        </div>
      </Drawer>
    </div>
  );
};

export default withStyles(styles)(ClippedDrawer);

现在,我尝试将功能组件转换为类:

interface Props {
   classes: any;
   selectedIndex: number;
}
class ClipperDrawer extends React.Component<any, Props> {
  constructor(props: any) {
    super(props);
    this.state = {
      classes: [],
      selectedIndex: 0
    };
  }

  public componentDidMount(): void {
    const path: string = window.location.pathname;

    switch (path) {
      case '/':
        this.setState({setSelectedIndex: 1})
        break;
      default:
        this.setState({setSelectedIndex: 1})
        break;
    }
  }

  public render() {
    const { classes, selectedIndex } = this.props;
    return (
      <div className={classes.root}>
        <Drawer
          className={classes.drawer}
          variant='permanent'
          classes={{
            paper: classes.drawerPaper
          }}
        >
          <div className={classes.toolbar} />
          <List>
            <Link to={'/'}>
              <ListItem
                button={true}
                selected={selectedIndex === 0}
                onClick={this.handleClickDashboard}
              >
                <ListItemIcon>
                  <DashboardIcon />
                </ListItemIcon>
                <ListItemText primary='Dashboard' />
              </ListItem>
            </Link>
            <Divider />
            <Link to={'/'}>
              <ListItem button={true} selected={selectedIndex === 2}>
                <ListItemIcon>
                  <BarChartIcon />
                </ListItemIcon>
                <ListItemText primary='Scenario Analysis' />
              </ListItem>
            </Link>
            <Divider />
            <Link to={'/'}>
              <ListItem button={true} selected={selectedIndex === 3}>
                <ListItemIcon>
                  <AssignmentIndIcon />
                </ListItemIcon>
                <ListItemText primary='Admin' />
              </ListItem>
            </Link>
          </List>
        </Drawer>
      </div>
    );
  }

  private handleClickDashboard = (
    event:
      | React.MouseEvent<HTMLLIElement>
      | React.MouseEvent<HTMLAnchorElement>
      | React.MouseEvent<HTMLDivElement>,
    index: number = 0
  ) => {
    const { setSelectedIndex } = this.state;
    this.setState({ setSelectedIndex: index });
  };

}

现在我想删除useEffect 钩子并将逻辑放入componentDidMounthandleClickDashboard 方法中。但是我收到一个错误说但是我收到错误

Argument of type '{ setSelectedIndex: number; }' is not assignable to parameter of type 'Props | ((prevState: Readonly<Props>, props: Readonly<any>) => Props | Pick<Props, "classes" | "selectedIndex"> | null) | Pick<...> | null'. Object literal may only specify known properties, and 'setSelectedIndex' does not exist in type 

【问题讨论】:

  • 您收到该错误是因为您的状态对象没有名为setSelectedIndex 的属性。它有一个名为selectedIndex 的属性,因此您应该使用this.setState({ selectedIndex: 1 })。顺便说一句,您似乎对 state 和 props 有一些混淆。

标签: reactjs typescript react-hooks


【解决方案1】:

您没有正确定义propsstate 的类型,

interface Props {
   classes: any;
   selectedIndex: number;
}
class ClipperDrawer extends React.Component<any, Props> {
// ------------------------------------------^

应该是:

interface Props {
   classes: any;
   selectedIndex: number;
}

interface State {
  setSelectedIndex: number;
// ... rest of the state values
}

class ClipperDrawer extends React.Component<Props, State> {

【讨论】:

  • 他尝试使用setSelectedIndex 作为属性名是错误地尝试将钩子用于非钩子。该属性应称为selectedIndex
【解决方案2】:

我有 setSelectedIndex 而不是 selectedIndex

【讨论】:

    猜你喜欢
    • 2023-03-25
    • 2020-06-06
    • 1970-01-01
    • 1970-01-01
    • 2020-06-04
    • 1970-01-01
    • 2021-10-14
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多