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

Mat*_*ber 45 reactjs material-ui

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

无效的挂接调用。挂钩只能在功能组件的主体内部调用。可能由于以下原因之一而发生:

  1. 您可能使用了不匹配的React和渲染器版本(例如React DOM)
  2. 您可能正在违反挂钩规则
  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;
Run Code Online (Sandbox Code Playgroud)

小智 83

我用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)
Run Code Online (Sandbox Code Playgroud)


Vik*_*mar 63

您好,而不是使用钩子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 HigherOrderComponent extends React.Component {

  render(){
    const { classes } = this.props;
    return (
      <Button className={classes.root}>Higher-order component</Button>
      );
  }
}

HigherOrderComponent.propTypes = {
  classes: PropTypes.object.isRequired,
};

export default withStyles(styles)(HigherOrderComponent);
Run Code Online (Sandbox Code Playgroud)

  • @VikasKumar 通过这种方法,我如何在我的样式中使用应用程序主题?Fe 提交: { margin: appTheme.spacing(3, 0, 2), }, (5认同)
  • 我一直在绕着这个错误和“无效的挂钩调用”错误跑来跑去-感谢您向正确的方向发展! (2认同)

Mat*_*ber 27

我们最终做的是停止使用类组件并创建功能组件,使用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;
Run Code Online (Sandbox Code Playgroud)

  • 我很困惑为什么这会遭到否决。React 已经非常清楚地表明类正在被带有 Hooks 的功能组件所取代。https://reactjs.org/docs/hooks-faq.html#should-i-use-hooks-classes-or-a-mix-of-both (5认同)
  • 我没有投反对票,但是在使用基于函数的组件时使用 xhr 以惰性方式设置初始状态是很痛苦的。使用类组件,我可以将初始状态设置为我想要的任何状态,然后使用 ajax,然后在响应到达后使用 setState。我完全不知道如何用一个函数很好地做到这一点。 (4认同)
  • 这被否决了,因为函数式编程在需要架构的实际应用程序中很糟糕。它加剧了 js 程序员编写大量意大利面条代码的趋势,这些代码确实非常难以阅读/遵循,而且不可能拆分成合理的组件。如果 React 正在推动这种方式,他们就犯了一个大错误,我不会跟随他们。 (4认同)
  • 对于使用 React 16.8 Hooks 更新或更高版本的人来说,我认为切换到函数是一个理想的解决方案。在 16.8 中,函数可以访问状态和生命周期钩子。 (2认同)