Otrzymuję poniższy błąd za każdym razem, gdy próbuję użyć makeStyles()
komponentu z metodami cyklu życia:
Nieprawidłowe połączenie z podniesioną słuchawką. Hooki można wywoływać tylko wewnątrz treści składnika funkcji. Może się to zdarzyć z jednego z następujących powodów:
- Możesz mieć niezgodne wersje Reacta i renderera (np. React DOM)
- Być może łamiesz Zasady korzystania z hooków
- Możesz mieć więcej niż jedną kopię Reacta w tej samej aplikacji
Poniżej znajduje się mały przykład kodu, który powoduje ten błąd. Inne przykłady przypisują klasy również elementom podrzędnym. W dokumentacji MUI nie mogę znaleźć niczego, co wskazywałoby na inne sposoby użycia makeStyles
i możliwość korzystania z metod cyklu życia.
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;
reactjs
material-ui
Matt Weber
źródło
źródło
invalid hook call
błędem - Dzięki za poprowadzenie mnie we właściwym kierunku !!theme
w swoimstyles
ciele (@SergeyAldoukhov już to powiedział). Kiedy go używam, pojawia się ten błąd: „Nie można odczytać właściwości 'X' o wartości undefined” iundefined
jesttheme
dokładnie! PróbowałemwithStyles(styles(myDefinedMuiTheme))(...)
i zadziałało poprawnie.makeStyles()
(styles = makeStyles(theme => ({...})
) . Ponadto, jeśli chcesz mieć styl zależny od motywu, zobacz mój poprzedni komentarz.Użyłem
withStyles
zamiastmakeStyle
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)
źródło
Skończyło się na tym, że przestaliśmy używać komponentów klas i utworzyliśmy komponenty funkcjonalne, używając
useEffect()
z Hooks API do metod cyklu życia . Dzięki temu można nadal korzystaćmakeStyles()
z metod cyklu życia bez dodawania komplikacji związanych z tworzeniem komponentów wyższego rzędu . Co jest znacznie prostsze.Przykład:
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;
źródło
useEffect
. W powyższym przypadku ustawiasz początkowy stan userName na pusty ciąg, a następnie po wykonaniu wywołania API upewnij sięuseEffect
, że użyjeszsetUserName(response)
. Dodam powyższy przykład i link do artykułu zawierającego więcej informacji na temat zastosowania metody useEffect w metodach cyklu życia. dev.to/prototyp/…useStyles
to hak React, który ma być używany w komponentach funkcjonalnych i nie może być używany w komponentach klas.Z Reacta:
Powinieneś także wywołać
useStyles
hook wewnątrz swojej funkcji, np.;function Welcome() { const classes = useStyles(); ...
Jeśli chcesz używać hooków, oto twój krótki komponent klasy zamieniony na komponent funkcjonalny;
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;
🏓 on ↓ CodeSandBox ↓
źródło
Inne rozwiązanie można zastosować dla komponentów klas - wystarczy zastąpić domyślne właściwości motywu MUI za pomocą MuiThemeProvider. Zapewni to większą elastyczność w porównaniu z innymi metodami - możesz użyć więcej niż jednego MuiThemeProvider wewnątrz komponentu nadrzędnego.
proste kroki:
proszę sprawdzić ten dokument, aby uzyskać więcej informacji: 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;
źródło
Zamiast konwertować klasę na funkcję, prostym krokiem byłoby utworzenie funkcji zawierającej jsx dla komponentu, który używa `` klas '', w twoim przypadku,
<container></container>
a następnie wywołaj tę funkcję wewnątrz zwracanej klasy render () jako tag. W ten sposób przenosisz zaczep do funkcji z klasy. U mnie zadziałało idealnie. W moim przypadku był to element,<table>
który przeniosłem do funkcji TableStmt na zewnątrz i nazwałem tę funkcję wewnątrz renderowania jako<TableStmt/>
źródło