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

IT技术 reactjs material-ui
2021-04-25 23:39:38

每当我尝试使用makeStyles()具有生命周期方法的组件时,都会收到以下错误

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

  1. 你可能有不匹配的 React 版本和渲染器(例如 React DOM)
  2. 你可能会违反 Hooks 规则
  3. 您可能在同一个应用程序中拥有多个 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;
4个回答

嗨,而不是使用钩子 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);

我用withStyles而不是makeStyle

前任 :

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)

我们最终做的是停止使用类组件并创建功能组件,使用useEffect()来自Hooks API 的生命周期方法这允许您仍然使用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;

useStyles 是一个 React 钩子,用于功能组件,不能用于类组件。

来自react:

Hooks 让您无需编写类即可使用状态和其他 React 功能。

你也应该在你的函数中调用useStyles钩子

function Welcome() {
  const classes = useStyles();
...

如果你想使用钩子,这里将你的简短类组件更改为功能组件;

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;

🏓 ↓ CodeSandBox ↓

编辑 React 钩子