【问题标题】:Can't use a react component with material-ui style classes in typescript不能在打字稿中使用带有 Material-ui 样式类的反应组件
【发布时间】:2020-11-21 11:05:00
【问题描述】:

我是 react 新手,目前开始了一个学习项目,其中我使用 typescript 3.7.2 和 material-ui 4.11.0 和 react 16.13.1。 我已将所有页面布局创建为功能组件,但在尝试将它们转换为类组件时(我发现它比使用钩子更容易)我收到以下错误(附加为 cmets), 我在 stackoverflow 上查看了其他一些答案,并尝试了不同的方法,但似乎都不起作用,我读过的大多数答案都是 2-3 年前的,我猜从那以后的一些变化是破坏性的变化,有没有人知道怎么解决吗?

import React from "react";
import Avatar from "@material-ui/core/Avatar";
import Button from "@material-ui/core/Button";
import CssBaseline from "@material-ui/core/CssBaseline";
import TextField from "@material-ui/core/TextField";
import FormControlLabel from "@material-ui/core/FormControlLabel";
import Checkbox from "@material-ui/core/Checkbox";
import Link from "@material-ui/core/Link";
import Grid from "@material-ui/core/Grid";
import LockOutlinedIcon from "@material-ui/icons/LockOutlined";
import Typography from "@material-ui/core/Typography";
import { makeStyles, withStyles } from "@material-ui/core/styles";
import Container from "@material-ui/core/Container";

const styles = makeStyles((theme) => ({
  paper: {
    marginTop: theme.spacing(8),
    display: "flex",
    flexDirection: "column",
    alignItems: "center",
  },
  avatar: {
    margin: theme.spacing(1),
    backgroundColor: theme.palette.secondary.main,
  },
  form: {
    width: "100%", // Fix IE 11 issue.
    marginTop: theme.spacing(1),
    marginBottom: theme.spacing(15),
  },
  submit: {
    margin: theme.spacing(3, 0, 2),
  },
}));

class LoginPage extends React.Component {
  render() {
    // Next line is first problem - I get :
    // **"Property 'classes' does not exist on type 'Readonly<{}> & Readonly<{ children?: ReactNode; }>'.ts(2339)"**
    const { classes } = this.props;
    return (
      <Container component="main" maxWidth="xs">
        <CssBaseline />
        <div className={classes.paper}>
          <Avatar className={classes.avatar}>
            <LockOutlinedIcon />
          </Avatar>
          <Typography component="h1" variant="h5">
            Sign in
          </Typography>
          <form className={classes.form} noValidate>
            <TextField
              variant="outlined"
              margin="normal"
              required
              fullWidth
              id="email"
              label="Email Address"
              name="email"
              autoComplete="email"
              autoFocus
            />
            <TextField
              variant="outlined"
              margin="normal"
              required
              fullWidth
              name="password"
              label="Password"
              type="password"
              id="password"
              autoComplete="current-password"
            />
            <FormControlLabel
              control={<Checkbox value="remember" color="primary" />}
              label="Remember me"
            />
            <Button
              type="submit"
              fullWidth
              variant="contained"
              color="primary"
              className={classes.submit}
            >
              Sign In
            </Button>
            <Grid container>
              <Grid item xs>
                <Link href="/reset-password" variant="body2">
                  Forgot password?
                </Link>
              </Grid>
              <Grid item>
                <Link href="/register" variant="body2">
                  {"Don't have an account? Sign Up"}
                </Link>
              </Grid>
            </Grid>
          </form>
        </div>
      </Container>
    );
  }
}

// 'styles' here produces a
**/*
Argument of type '(props?: any) => Record<"paper" | "avatar" | "form" | "submit", string>' is not assignable to parameter of type 'Styles<Theme, {}, "paper" | "avatar" | "form" | "submit">'.
  Type '(props?: any) => Record<"paper" | "avatar" | "form" | "submit", string>' is not assignable to type 'StyleRulesCallback<Theme, {}, "paper" | "avatar" | "form" | "submit">'.
    Call signature return types 'Record<"paper" | "avatar" | "form" | "submit", string>' and 'Record<"paper" | "avatar" | "form" | "submit", CSSProperties | CreateCSSProperties<{}> | PropsFunc<{}, CreateCSSProperties<{}>>>' are incompatible.
      The types of 'paper' are incompatible between these types.
        Type 'string' is not assignable to type 'CSSProperties | CreateCSSProperties<{}> | PropsFunc<{}, CreateCSSProperties<{}>>'.ts(2345)
*/**
export default withStyles(styles)(LoginPage);

【问题讨论】:

标签: reactjs typescript material-ui


【解决方案1】:

我也是使用 TypeScript 的 React Material-UI 的新手,我也遇到过同样的问题。请参阅此工作示例:AppBarSample.tsx

你应该添加一些类型定义:

  1. const styles = makeStyles((theme) => ({
    → 
    const styles: Styles<Theme, {}, string> = (theme: Theme) => ({
    
  2. class LoginPage extends React.Component {
    →
    interface IProps {
      classes?: any;
    }
    class LoginPage extends React.Component<IProps, any> {
    

请参阅this diffworking implementation 了解更多信息。

【讨论】:

    【解决方案2】:

    错误是makeStyles returns a hook,不能与 withStyles 一起使用。

    对于您的高阶组件(HOC:LoginPage),您应该像这样遵循styles API

    替换

       const styles = makeStyles((theme) => ({
        paper: {
         marginTop: theme.spacing(8),...
    

        const styles = {
         paper: {
          marginTop: theme.spacing(8),...
    

    withStyles 接受 CSSProperties 类型的对象作为参数,而不是字符串。 makeStyles 返回一个类名。

    祝你好运,如果我解决了你的问题,请告诉我。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2021-06-30
      • 2023-03-06
      • 2020-05-08
      • 2020-12-05
      • 2018-01-08
      • 2021-10-10
      • 2021-10-15
      相关资源
      最近更新 更多