Recibo el siguiente error cada vez que intento usarlo makeStyles()
con un componente con métodos de ciclo de vida:
Llamada de gancho no válida. Los ganchos solo se pueden llamar dentro del cuerpo de un componente de función. Esto podría suceder por una de las siguientes razones:
- Es posible que tenga versiones no coincidentes de React y el renderizador (como React DOM)
- Puede que estés infringiendo las reglas de los ganchos
- Es posible que tenga más de una copia de React en la misma aplicación
A continuación se muestra un pequeño ejemplo de código que produce este error. Otros ejemplos también asignan clases a elementos secundarios. No puedo encontrar nada en la documentación de MUI que muestre otras formas de usar makeStyles
y tenga la capacidad de usar métodos de ciclo de vida.
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;
fuente
invalid hook call
error: ¡¡Gracias por llevarme en la dirección correcta !!theme
en tustyles
cuerpo (@SergeyAldoukhov ya ha dicho esto). Cuando lo uso, aparece este error: "No se puede leer la propiedad 'X' de indefinido" yundefined
estheme
exactamente! Lo intentéwithStyles(styles(myDefinedMuiTheme))(...)
y funcionó correctamente.makeStyles()
(styles = makeStyles(theme => ({...})
) . Además, si desea un estilo dependiente del tema, consulte mi comentario anterior.Usé en
withStyles
lugar demakeStyle
EX:
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)
fuente
Lo que terminamos haciendo fue dejar de usar los componentes de la clase y crear componentes funcionales, usando
useEffect()
la API Hooks para los métodos del ciclo de vida . Esto le permite seguir utilizando losmakeStyles()
métodos de ciclo de vida sin agregar la complicación de crear componentes de orden superior . Que es mucho más sencillo.Ejemplo:
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;
fuente
useEffect
. En el caso anterior, está configurando el estado inicial de userName en una cadena vacía, luego, después de realizar una llamada a la API, asegúrese deuseEffect
usarsetUserName(response)
. Agregaré un ejemplo arriba y un enlace a un artículo con más información sobre el uso de useEffect para los métodos del ciclo de vida. dev.to/prototyp/…useStyles
es un gancho de React que está destinado a ser utilizado en componentes funcionales y no se puede utilizar en componentes de clase.De React:
También debes llamar a
useStyles
hook dentro de tu función como;function Welcome() { const classes = useStyles(); ...
Si desea utilizar ganchos, aquí está su breve componente de clase convertido en componente funcional;
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;
🏓 en ↓ CodeSandBox ↓
fuente
Se puede usar otra solución para los componentes de la clase: simplemente anule las propiedades predeterminadas del tema MUI con MuiThemeProvider. Esto le dará más flexibilidad en comparación con otros métodos; puede usar más de un MuiThemeProvider dentro de su componente principal.
pasos sencillos:
Por favor, consulte este documento para obtener más detalles: 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;
fuente
En lugar de convertir la clase en una función, un paso fácil sería crear una función para incluir el jsx para el componente que usa las 'clases', en su caso,
<container></container>
y luego llamar a esta función dentro del retorno de la clase render () como una etiqueta. De esta manera, está moviendo el enlace a una función de la clase. Funcionó perfectamente para mí. En mi caso, fue un<table>
que moví a una función: TableStmt afuera y llamé a esta función dentro del render como<TableStmt/>
fuente