如何在Material Ui中使用useStyle为类组件设置样式

68

我想使用useStyle来为类组件设置样式,但是这很容易通过钩子函数实现。但是我希望使用类组件而不是钩子函数,但我想不出如何实现。

我想使用useStyle来为类组件设置样式,但是这很容易通过钩子函数实现。但是我希望使用类组件而不是钩子函数,但我想不出如何实现。

import React,{Component} from 'react';
import Avatar from '@material-ui/core/Avatar';
import { makeStyles } from '@material-ui/core/styles';
import LockOutlinedIcon from '@material-ui/icons/LockOutlined';


    const useStyles = makeStyles(theme => ({
      '@global': {
        body: {
          backgroundColor: theme.palette.common.white,
        },
      },
      paper: {
        marginTop: theme.spacing(8),
        display: 'flex',
        flexDirection: 'column',
        alignItems: 'center',
      },
      avatar: {
        margin: theme.spacing(1),
        backgroundColor: theme.palette.secondary.main,
      }
}));

class SignIn extends Component{
  const classes = useStyle(); // how to assign UseStyle
  render(){
     return(
    <div className={classes.paper}>
    <Avatar className={classes.avatar}>
      <LockOutlinedIcon />
    </Avatar>
    </div>
  }
}
export default SignIn;

你错过了括号,应该是 const classes = useStyle(); - kamprasad
7个回答

91
你可以像这样做:
import { withStyles } from "@material-ui/core/styles";

const styles = theme => ({
  root: {
    backgroundColor: "red"
  }
});

class ClassComponent extends Component {
  state = {
    searchNodes: ""
  };

  render() {
    const { classes } = this.props;
    return (
      <div className={classes.root}>Hello!</div>
    );
  }
}

export default withStyles(styles, { withTheme: true })(ClassComponent);

如果您没有使用主题,请忽略 withTheme: true


为了在 TypeScript 中使其工作,需要进行一些更改:

import { createStyles, withStyles, WithStyles } from "@material-ui/core/styles";

const styles = theme => createStyles({
  root: {
    backgroundColor: "red"
  }
});

interface Props extends WithStyles<typeof styles>{ }

class ClassComponent extends Component<Props> {

// the rest of the code stays the same

Material UI使用Higher-order组件API的官方示例:https://material-ui.com/styles/basics/#higher-order-component-api - Oliver Kocsis
1
谢谢。我试过了,即使我们有一个主题,我们也不需要 { withTheme: true } - Mir-Ismaili
我们需要的英雄,但不配拥有!我们已经远离基于类的组件,与React.FC相比,它们很混乱,但为了使模态框与Material-UI一起工作,我们必须使用基于类的组件。这在TypeScript中完美地运行。 - Pierre
不幸的是,这似乎与TypeScript中的refs不兼容。 以前我可以使用useRef<MyComponent>(null)对组件进行引用,但现在不再起作用,因为MyComponent不再是一种类型。 更令人烦恼的是,TypeScript报告“属性'ref'不存在”于从withStyles()()返回的组件上,但一个丑陋的hack涉及到any使错误消失了,并且代码似乎可以工作。 - Qwertie

25

对于类组件,您可以使用withStyles而不是makeStyles

import { withStyles } from '@material-ui/core/styles';

const useStyles = theme => ({
fab: {
  position: 'fixed',
  bottom: theme.spacing(2),
  right: theme.spacing(2),
},
  });

class ClassComponent extends Component {
   render() {
            const { classes } = this.props;

            {/** your UI components... */}
      }
} 


export default withStyles(useStyles)(ClassComponent)

6
我遇到了同样的问题,按照你的建议操作,但是道具没有样式呈现。有什么技巧吗?谢谢。 - Maralc

7

嘿,我曾经遇到过类似的问题。我通过将 makeStyles 替换为 withStyles 来解决它,然后在执行像 const classes = useStyle(); 这样的代码时,将其替换为 const classes = useStyle;

你可以注意到,useStyle 不应该是一个函数调用,而应该是一个变量分配。

在进行这些更改之后,那应该可以正常工作了。


6

useStyles 是一个 React hook,只能在函数组件中使用。

这行代码创建了这个 hook:

const useStyles = makeStyles(theme => ({ /* ... */ });

您正在函数组件中使用它来创建类对象:

const classes = useStyles();


然后在jsx中你使用类(class):
<div className={classes.paper}>

建议使用的资源: https://material-ui.com/styles/basics/ https://reactjs.org/docs/hooks-intro.html

2
对于类组件,您可以使用 withStyles - Ryan Cogswell
1
在此答案中链接的文档中,它位于“高阶组件 API”标题下。 - Ryan Cogswell

3

就像其他已经回答的问题一样,您应该使用withStyles来增强组件并通过属性传递classes。我已经将Material-UI压力测试示例修改为使用类组件的变体。

请注意,当您只想使用样式时,通常不需要使用withTheme: true选项。在这个例子中需要它,因为主题的实际值在渲染中使用。设置此选项使theme通过类属性可用。即使未设置此选项,也应始终提供classes属性。

const useStyles = MaterialUI.withStyles((theme) => ({
  root: (props) => ({
    backgroundColor: props.backgroundColor,
    color: theme.color,
  }),
}), {withTheme: true});

const Component = useStyles(class extends React.Component {
  rendered = 0;

  render() {
    const {classes, theme, backgroundColor} = this.props;
    return (
      <div className={classes.root}>
        rendered {++this.rendered} times
        <br />
        color: {theme.color}
        <br />
        backgroundColor: {backgroundColor}
      </div>
    );
  }
});

function StressTest() {
  const [color, setColor] = React.useState('#8824bb');
  const [backgroundColor, setBackgroundColor] = React.useState('#eae2ad');

  const theme = React.useMemo(() => ({ color }), [color]);
  const valueTo = setter => event => setter(event.target.value);

  return (
    <MaterialUI.ThemeProvider theme={theme}>
      <div>
        <fieldset>
          <div>
            <label htmlFor="color">theme color: </label>
            <input
              id="color"
              type="color"
              onChange={valueTo(setColor)}
              value={color}
            />
          </div>
          <div>
            <label htmlFor="background-color">background-color property: </label>
            <input
              id="background-color"
              type="color"
              onChange={valueTo(setBackgroundColor)}
              value={backgroundColor}
            />
          </div>
        </fieldset>
        <Component backgroundColor={backgroundColor} />
      </div>
    </MaterialUI.ThemeProvider>
  );
}

ReactDOM.render(<StressTest />, document.querySelector("#root"));
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Roboto:300,400,500,700&display=swap" />
<link rel="stylesheet" href="https://fonts.googleapis.com/icon?family=Material+Icons" />
<script src="https://unpkg.com/react@16/umd/react.production.min.js"></script>
<script src="https://unpkg.com/react-dom@16/umd/react-dom.production.min.js"></script>
<script src="https://unpkg.com/@material-ui/core@4/umd/material-ui.production.min.js"></script>
<div id="root"></div>


1

还有一种方法可以实现这个,虽然有点绕。

有些人可能会说这并没有真正回答问题,但我认为它确实回答了。最终结果是useStyles()提供了基于类的、多部分父组件的样式。

在我的情况下,我需要一个标准的Javascript类导出,这样我就可以调用new MyClass()而不会出现MyClass不是构造函数的错误。

import { Component } from "./react";
import { makeStyles } from "@material-ui/core/styles";

const useStyles = makeStyles((theme) => ({
  someClassName: {
    ...
  }
}));

export default class MyComponent extends Component {
  render() {
    return <RenderComponent {...this.props} />;
  }
}

function RenderComponent(props) {
  const classes = useStyles();

  return (
    /* JSX here */
  );
}

0

如何在类组件中的ClassName中添加多个类

import { withStyles } from "@material-ui/core/styles";

const styles = theme => ({
  root: {
    backgroundColor: "red"
  },
  label: {
    backGroundColor:"blue"
 }
});

class ClassComponent extends Component {
  state = {
    searchNodes: ""
  };

  render() {
    const { classes } = this.props;//   
    return (
      <div className={classes.root + classes.label}>Hello!</div> //i want to add label style also with
    );
  }
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接