J'obtiens l'erreur ci-dessous chaque fois que j'essaye d'utiliser makeStyles()
avec un composant avec des méthodes de cycle de vie:
Appel de hook non valide. Les hooks ne peuvent être appelés qu'à l'intérieur du corps d'un composant de fonction. Cela peut se produire pour l'une des raisons suivantes:
- Vous pouvez avoir des versions incompatibles de React et du moteur de rendu (comme React DOM)
- Vous enfreignez peut-être les règles des Hooks
- Vous pouvez avoir plus d'une copie de React dans la même application
Voici un petit exemple de code qui produit cette erreur. D'autres exemples affectent également des classes aux éléments enfants. Je ne trouve rien dans la documentation de MUI qui montre d'autres façons d'utiliser makeStyles
et j'ai la possibilité d'utiliser des méthodes de cycle de vie.
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;
la source
invalid hook call
erreur - Merci de m'avoir amené dans la bonne direction !!theme
dans votrestyles
corps (@SergeyAldoukhov l'a déjà dit). Quand je l'utilise, j'obtiens cette erreur: "Impossible de lire la propriété 'X' de undefined" etundefined
c'esttheme
exactement! J'ai essayéwithStyles(styles(myDefinedMuiTheme))(...)
et cela a fonctionné correctement.makeStyles()
(styles = makeStyles(theme => ({...})
) . De plus, si vous voulez un style dépendant du thème, consultez mon commentaire précédent.J'ai utilisé
withStyles
au lieu 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)
la source
Ce que nous avons fini par faire, c'est cesser d'utiliser les composants de classe et créer des composants fonctionnels, en utilisant
useEffect()
l' API Hooks pour les méthodes de cycle de vie . Cela vous permet de continuer à utiliser lesmakeStyles()
méthodes du cycle de vie sans ajouter la complication de la création de composants d'ordre supérieur . Ce qui est beaucoup plus simple.Exemple:
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;
la source
useEffect
. Dans le cas ci-dessus, vous définissez l'état initial de userName sur une chaîne vide, puis après un appel d'API effectué, assurez-useEffect
vous de l'utilisersetUserName(response)
. J'ajouterai un exemple ci-dessus et un lien vers un article avec plus d'informations sur l'utilisation de useEffect pour les méthodes de cycle de vie. dev.to/prototyp/…useStyles
est un hook React destiné à être utilisé dans les composants fonctionnels et ne peut pas être utilisé dans les composants de classe.De React:
Vous devez également appeler
useStyles
hook dans votre fonction comme;function Welcome() { const classes = useStyles(); ...
Si vous souhaitez utiliser des hooks, voici votre bref composant de classe transformé en composant fonctionnel;
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;
🏓 sur ↓ CodeSandBox ↓
la source
Une autre solution peut être utilisée pour les composants de classe - il suffit de remplacer les propriétés de thème MUI par défaut avec MuiThemeProvider. Cela donnera plus de flexibilité par rapport aux autres méthodes - vous pouvez utiliser plus d'un MuiThemeProvider dans votre composant parent.
étapes simples:
veuillez consulter ce document pour plus de détails: 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;
la source
Au lieu de convertir la classe en fonction, une étape facile serait de créer une fonction pour inclure le jsx pour le composant qui utilise les 'classes', dans votre cas
<container></container>
, puis appelez cette fonction dans le retour de la classe render () comme étiquette. De cette façon, vous déplacez le crochet vers une fonction de la classe. Cela a parfaitement fonctionné pour moi. Dans mon cas, c'est une fonction<table>
que j'ai déplacée vers une fonction - TableStmt à l'extérieur et j'ai appelé cette fonction à l'intérieur du rendu comme<TableStmt/>
la source