如何使用 makStyles 对组件进行样式化,同时材料用户界面中仍然保留生命周期方法?

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

Invalid hook call. Hooks can only be called inside of the body of a function component. This could happen for one of the following reasons:

  1. 您可能有不匹配的 React 版本和渲染器(例如 React DOM) - You might have mismatching versions of React and the renderer (such as 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 ;
}
return (



);
}
}


export default Welcome;
201996 次浏览

您应该使用高阶组件 API,而不是使用 Hook API,正如前面提到的 给你

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

import React from 'react';
import PropTypes from 'prop-types';
import { withStyles } from '@material-ui/core/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);

我们最终停止使用类组件,并从 用于生命周期方法的 Hooks API中创建了 Functional Component,使用 useEffect()。这使您仍然可以使用 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;

与将类转换为函数不同,一个简单的步骤是创建一个函数来包含使用“ class”的组件的 jsx,在您的例子中是 <container></container>,然后在类 render ()的返回中以标记的形式调用这个函数。通过这种方式,您可以从类中移出一个函数的挂钩。对我来说很有效。在我的例子中,它是一个 <table>,我将它移动到外部的一个函数 TableStmt 中,并在呈现中以 <TableStmt/>的形式调用这个函数

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

返回文章页面反应:

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;

在 & darr; 代码沙箱 & darr;

Edit React hooks

我用的是 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)

另一种解决方案可以用于类组件- 只需使用 MuiThemeProvider 覆盖默认的 MUI 主题属性。 与其他方法相比,这将提供更大的灵活性——您可以在父组件中使用多个 MuiThemeProvider。

简单步骤:

  1. 将 MuiThemeProvider 导入到类组件
  2. 将 createMuiTheme 导入到类组件
  3. 创造新的主题
  4. 用 MuiThemeProvider 和自定义主题包装要样式化的目标 MUI 组件

请查阅这份文件了解更多细节: Https://material-ui.com/customization/theming/

import React from 'react';
import PropTypes from 'prop-types';
import Button from '@material-ui/core/Button';


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


const InputTheme = createMuiTheme({
overrides: {
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 (
<MuiThemeProvider theme={InputTheme}>
<Button className={classes.root}>Higher-order component</Button>
</MuiThemeProvider>
);
}
}


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


export default HigherOrderComponent;

您正在函数的外部调用 useStyles hook,这就是原因

除了@vikas-kumar 提供的答案之外,还可以使用在被样式化的组件上设置的 props,例如。

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: props => props.height,
padding: '0 30px',
},
});

因此,应用样式的 height可以由

<HigherOrderComponentUsageExample height={48}/>

关于动态样式的更多细节可以在这里获得: https://material-ui.com/styles/basics/#adapting-the-higher-order-component-api