【问题标题】:How to use useStyle to style Class Component in Material Ui如何使用 useStyle 在 Material Ui 中设置类组件的样式
【发布时间】:2019-10-26 12:26:36
【问题描述】:

我想使用 useStyle 来设置 Class Component 的样式。但这可以很容易地完成钩子。但我想改用组件。但我不知道该怎么做。

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

标签: javascript reactjs material-ui react-hooks react-component


【解决方案1】:

你可以这样做:

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 中使用高阶组件 API 的官方示例:material-ui.com/styles/basics/#higher-order-component-api
  • 谢谢。 正如我所尝试的,即使我们有主题,我们也不需要{ withTheme: true }
  • 我们需要但不值得的英雄!我们已经远离了基于类的组件,与 React.FC 相比,它们是一团糟,但是要使模态与 Material-UI 一起工作,我们必须使用基于类的组件。这与 Typescript 完美配合。
  • 不幸的是,这似乎与 TypeScript 中的 refs 不兼容。以前我可以使用useRef&lt;MyComponent&gt;(null) 对组件进行引用,但他不再有效,因为MyComponent 不再是一种类型。更令人不安的是,TypeScript 报告从 withStyles()() 返回的组件上的“属性 'ref' 不存在”,但涉及 any 的丑陋 hack 使错误消失,代码似乎工作。
【解决方案2】:

对于类组件,您可以使用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)

【讨论】:

  • 我也遇到过同样的问题,听从了你的建议,但是没有样式的道具是空的。有小费吗?谢谢。
【解决方案3】:

嘿,我遇到了类似的问题。我通过将makeStyles 替换为withStyles 来解决它,然后在执行const classes = useStyle(); 之类的操作时,将其替换为const classes = useStyle;

您注意到useStyle 不应该是函数调用,而是变量赋值。

在您进行这些更改后应该可以正常工作。

【讨论】:

    【解决方案4】:

    useStyles 是一个反应钩子。只能在函数组件中使用。

    这一行创建了钩子:

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

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

    const classes = useStyles();
    
    

    然后在 jsx 中使用类:

    <div className={classes.paper}>
    

    推荐资源: https://material-ui.com/styles/basics/ https://reactjs.org/docs/hooks-intro.html

    【讨论】:

    • 类组件可以使用withStyles
    • 在此答案链接的文档中,它位于“高阶组件 API”标题下。
    【解决方案5】:

    就像已经说明的其他答案一样,您应该使用withStyles 来扩充组件并通过属性传递classes。我冒昧地将Material-UI stress test example 修改为使用类组件的变体。

    请注意,当您只想使用样式时,通常不需要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>

    【讨论】:

      【解决方案6】:

      还有另一种方法可以做到这一点,尽管有点变通方法。

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

      在我的例子中,我需要一个标准的 Javascript 类导出,这样我就可以调用 new MyClass() 而不会出现 MyClass is not a constructor 错误。

      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 */
        );
      }
      

      【讨论】:

        【解决方案7】:

        如何使用类组件在 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
            );
          }
        }
        

        【讨论】:

          猜你喜欢
          • 2021-02-01
          • 2021-06-02
          • 2022-08-10
          • 2021-02-19
          • 1970-01-01
          • 2018-11-20
          • 2020-08-05
          • 1970-01-01
          • 2021-02-05
          相关资源
          最近更新 更多