Reactjs 如何使用makeStyles设置组件样式,并且在材质UI中仍然具有生命周期方法?

Reactjs 如何使用makeStyles设置组件样式,并且在材质UI中仍然具有生命周期方法?,reactjs,material-ui,Reactjs,Material Ui,每当我尝试将makeStyles()与具有生命周期方法的组件一起使用时,就会出现以下错误: 无效的钩子调用。钩子只能在函数组件的主体内部调用。这可能是由于以下原因之一: React和渲染器的版本可能不匹配(例如React DOM) 你可能违反了钩子的规则 同一应用程序中可能有多个React副本 下面是产生此错误的代码的一个小示例。其他示例也将类分配给子项。我在MUI的文档中找不到任何显示使用makeStyles的其他方法以及使用生命周期方法的能力的内容 import React, { C

每当我尝试将
makeStyles()
与具有生命周期方法的组件一起使用时,就会出现以下错误:

无效的钩子调用。钩子只能在函数组件的主体内部调用。这可能是由于以下原因之一:

  • React和渲染器的版本可能不匹配(例如React DOM)
  • 你可能违反了钩子的规则
  • 同一应用程序中可能有多个React副本
  • 下面是产生此错误的代码的一个小示例。其他示例也将类分配给子项。我在MUI的文档中找不到任何显示使用
    makeStyles
    的其他方法以及使用生命周期方法的能力的内容

        import React, { Component } from 'react';
        import { Redirect } from 'react-router-dom';
    
        import { Container, makeStyles } from '@material-ui/core';
    
        import LogoButtonCard from '../molecules/Cards/LogoButtonCard';
    
        const useStyles = makeStyles(theme => ({
          root: {
            display: 'flex',
            alignItems: 'center',
            justifyContent: 'center',
          },
        }));
    
        const classes = useStyles();
    
        class Welcome extends Component {
          render() {
            if (this.props.auth.isAuthenticated()) {
              return <Redirect to="/" />;
            }
            return (
              <Container maxWidth={false} className={classes.root}>
                <LogoButtonCard
                  buttonText="Enter"
                  headerText="Welcome to PlatformX"
                  buttonAction={this.props.auth.login}
                />
              </Container>
            );
          }
        }
    
        export default Welcome;
    
    import React,{Component}来自'React';
    从'react router dom'导入{Redirect};
    从“@material ui/core”导入{Container,makeStyles};
    从“../molecles/Cards/logobutoncard”导入logobutoncard;
    const useStyles=makeStyles(主题=>({
    根目录:{
    显示:“flex”,
    对齐项目:“居中”,
    为内容辩护:“中心”,
    },
    }));
    const classes=useStyles();
    类欢迎扩展组件{
    render(){
    if(this.props.auth.isAuthenticated()){
    返回;
    }
    返回(
    );
    }
    }
    出口默认值欢迎;
    
    您好,您应该使用前面提到的高阶组件API,而不是使用钩子API

    我将修改文档中的示例,以满足您对类组件的需求

    import React from 'react';
    import PropTypes from 'prop-types';
    import { withStyles } from '@material-ui/styles';
    import Button from '@material-ui/core/Button';
    
    const styles = theme => ({
      root: {
        background: 'linear-gradient(45deg, #FE6B8B 30%, #FF8E53 90%)',
        border: 0,
        borderRadius: 3,
        boxShadow: '0 3px 5px 2px rgba(255, 105, 135, .3)',
        color: 'white',
        height: 48,
        padding: '0 30px',
      },
    });
    
    class HigherOrderComponentUsageExample extends React.Component {
      
      render(){
        const { classes } = this.props;
        return (
          <Button className={classes.root}>This component is passed to an HOC</Button>
          );
      }
    }
    
    HigherOrderComponentUsageExample.propTypes = {
      classes: PropTypes.object.isRequired,
    };
    
    export default withStyles(styles)(HigherOrderComponentUsageExample);
    
    从“React”导入React;
    从“道具类型”导入道具类型;
    从'@material ui/styles'导入{withStyles};
    从“@material ui/core/Button”导入按钮;
    常量样式=主题=>({
    根目录:{
    背景:“线性梯度(45度,Fe6B30%,FF8E53 90%),
    边界:0,
    边界半径:3,
    boxShadow:'0 3px 5px 2px rgba(255、105、135、3)',
    颜色:'白色',
    身高:48,
    填充:“0 30px”,
    },
    });
    类HigherOrderComponentUsageExample扩展React.Component{
    render(){
    const{classes}=this.props;
    返回(
    此组件被传递给一个HOC
    );
    }
    }
    HigherOrderComponentusExample.propTypes={
    类:PropTypes.object.isRequired,
    };
    使用样式导出默认值(样式)(高级命令组件示例);
    
    我们最终做的是停止使用类组件,并从中创建功能组件。这允许您将
    makeStyles()
    与生命周期方法一起使用。这要简单得多

    例如:

    import React, { useEffect, useState } from 'react';
    import axios from 'axios';
    import { Redirect } from 'react-router-dom';
    
    import { Container, makeStyles } from '@material-ui/core';
    
    import LogoButtonCard from '../molecules/Cards/LogoButtonCard';
    
    const useStyles = makeStyles(theme => ({
      root: {
        display: 'flex',
        alignItems: 'center',
        justifyContent: 'center',
        margin: theme.spacing(1)
      },
      highlight: {
        backgroundColor: 'red',
      }
    }));
    
    // Highlight is a bool
    const Welcome = ({highlight}) => { 
      const [userName, setUserName] = useState('');
      const [isAuthenticated, setIsAuthenticated] = useState(true);
      const classes = useStyles();
    
      useEffect(() => {
        axios.get('example.com/api/username/12')
             .then(res => setUserName(res.userName));
      }, []);
    
      if (!isAuthenticated()) {
        return <Redirect to="/" />;
      }
      return (
        <Container maxWidth={false} className={highlight ? classes.highlight : classes.root}>
          <LogoButtonCard
            buttonText="Enter"
            headerText={isAuthenticated && `Welcome, ${userName}`}
            buttonAction={login}
          />
       </Container>
       );
      }
    }
    
    export default Welcome;
    
    import React,{useffect,useState}来自“React”;
    从“axios”导入axios;
    从'react router dom'导入{Redirect};
    从“@material ui/core”导入{Container,makeStyles};
    从“../molecles/Cards/logobutoncard”导入logobutoncard;
    const useStyles=makeStyles(主题=>({
    根目录:{
    显示:“flex”,
    对齐项目:“居中”,
    为内容辩护:“中心”,
    页边空白:主题。间距(1)
    },
    亮点:{
    背景颜色:“红色”,
    }
    }));
    //这是一个难题
    常量欢迎=({highlight})=>{
    const[userName,setUserName]=useState(“”);
    const[isAuthenticated,setIsAuthenticated]=useState(true);
    const classes=useStyles();
    useffect(()=>{
    get('example.com/api/username/12')
    。然后(res=>setUserName(res.userName));
    }, []);
    如果(!isAuthenticated()){
    返回;
    }
    返回(
    );
    }
    }
    出口默认值欢迎;
    
    不必将类转换为函数,一个简单的步骤是创建一个函数来包含使用“类”的组件的jsx,在您的例子中是
    ,然后在类render()的返回中作为标记调用此函数。这样,您就可以将钩子从类中移出到函数。它对我非常有效。在我的例子中,它是一个
    ,我移动到函数表tmt外部,并在渲染内部调用该函数,因为
    useStyles
    是一个React钩子,用于功能组件,不能用于类组件

    钩子允许您使用状态和其他React特性,而无需编写 班级

    您还应该调用
    useStyles
    hook-like


    如果你想使用钩子,这里是你的简单类组件变成了功能组件

    import React from "react";
    import { Container, makeStyles } from "@material-ui/core";
    
    const useStyles = makeStyles({
      root: {
        background: "linear-gradient(45deg, #FE6B8B 30%, #FF8E53 90%)",
        border: 0,
        borderRadius: 3,
        boxShadow: "0 3px 5px 2px rgba(255, 105, 135, .3)",
        color: "white",
        height: 48,
        padding: "0 30px"
      }
    });
    
    function Welcome() {
      const classes = useStyles();
      return (
        <Container className={classes.root}>
          <h1>Welcome</h1>
        </Container>
      );
    }
    
    export default Welcome;
    
    从“React”导入React;
    从“@material ui/core”导入{Container,makeStyles}”;
    const useStyles=makeStyles({
    根目录:{
    背景:“线性梯度(45度,#FE6B8B 30%,#FF8E53 90%)”,
    边界:0,
    边界半径:3,
    boxShadow:“0 3px 5px 2px rgba(255、105、135、3)”,
    颜色:“白色”,
    身高:48,
    填充:“0 30px”
    }
    });
    函数欢迎(){
    const classes=useStyles();
    返回(
    欢迎
    );
    }
    出口默认值欢迎;
    


    我使用了带有样式的
    而不是
    makeStyle

    例:

    从'@materialui/core/styles'导入{withStyles};
    从“React”导入React,{Component};
    const useStyles=主题=>({
    根目录:{
    flexGrow:1,
    },
    });
    类应用程序扩展组件{
    render(){
    const{classes}=this.props;
    返回(
    试验
    )
    }
    } 
    使用样式导出默认值(使用样式)(应用程序)
    
    另一种解决方案可用于类组件- 只需使用MuiThemeProvider覆盖默认的MUI主题属性。 与其他方法相比,这将提供更大的灵活性-您可以在父组件中使用多个MuiThemeProvider

    简单步骤:

  • 将MuiThemeProvider导入类组件
  • 将CreateMuiteme导入类组件
  • 创建新主题
  • import React from "react";
    import { Container, makeStyles } from "@material-ui/core";
    
    const useStyles = makeStyles({
      root: {
        background: "linear-gradient(45deg, #FE6B8B 30%, #FF8E53 90%)",
        border: 0,
        borderRadius: 3,
        boxShadow: "0 3px 5px 2px rgba(255, 105, 135, .3)",
        color: "white",
        height: 48,
        padding: "0 30px"
      }
    });
    
    function Welcome() {
      const classes = useStyles();
      return (
        <Container className={classes.root}>
          <h1>Welcome</h1>
        </Container>
      );
    }
    
    export default Welcome;
    
    import { withStyles } from '@material-ui/core/styles';
    import React, {Component} from "react";
    
    const useStyles = theme => ({
            root: {
               flexGrow: 1,
             },
      });
    
    class App extends Component {
           render() {
                    const { classes } = this.props;
                    return(
                        <div className={classes.root}>
                           Test
                    </div>
                    )
              }
    } 
    
    export default withStyles(useStyles)(App)