-1

I am a react beginner. I use hooks in the class and the program reports errors

src\page\App.js Line 41:35: React Hook "React.useState" cannot be called in a class component. React Hooks must be called in a React function component or a custom React Hook function react-hooks/rules-of-hooks Line 44:39: React Hook "React.useState" cannot be called in a class component. React Hooks must be called in a React function component or a custom React Hook function react-hooks/rules-of-hooks Search for the keywords to learn more about each error.

this is my code

import './App.css';
import React from "react";
import {BottomNavigation, BottomNavigationAction} from "@material-ui/core";
import {AccountCircle, Home, Info} from "@material-ui/icons";
import makeStyles from "@material-ui/core/styles/makeStyles";
import Grid from "@material-ui/core/Grid";
import AppBar from "@material-ui/core/AppBar";
import Toolbar from "@material-ui/core/Toolbar";
import Typography from "@material-ui/core/Typography";
import styled from "@material-ui/core/styles/styled";


class App extends React.Component {
    render() {

        makeStyles(() => ({
            title: {
                color: "#ffffff"
            },
            toolbar: {
                background: "#3f51b5"
            },
            contents: {
                marginBottom: "100px"
            },
            bottomNavigation: {
                left: '0px',
                right: '0px',
                position: 'fixed',
                bottom: '0px',
            }
        }));
        const {classes} = this.props

        const MyGrid = styled(Grid)({
            marginTop: 10,
        });


        //切换标签选中的钩子
        const [value, setValue] = React.useState('home');

        //切换toolbar的钩子
        const [tbValue, setTbValue] = React.useState("主页");


        const handleChange = (event, newValue) => {
            setValue(newValue);
            console.log("switch" + newValue)
            //切换tb的字
            switch (newValue) {
                case 'home':
                    setTbValue("主页");
                    this.props.history.push('/home/user_login');
                    break;
                case 'info':
                    setTbValue("信息");
                    this.props.history.push('/home/info');
                    break;
                case 'me':
                    setTbValue("我的");
                    this.props.history.push('/home/me');
                    break;
            }
        };


        return (
            <div>
                <AppBar position="static" style={{left: "0", right: "0"}}>
                    <Toolbar className={classes.toolbar}>
                        <Typography className={classes.title}>
                            {tbValue}
                        </Typography>
                    </Toolbar>
                </AppBar>

                {/*内容区*/}
                <div className={classes.contents}>
                    <div>
                        <MyGrid container direction={'column'} justify={"center"}
                                alignContent={"center"}>
                            {this.props.children}
                        </MyGrid>
                    </div>
                </div>


                <BottomNavigation className={classes.bottomNavigation}
                                  value={value}
                                  onChange={handleChange} showLabels>
                    <BottomNavigationAction label="主页" value='home' icon={<Home/>}/>
                    <BottomNavigationAction label="信息" value='info' icon={<Info/>}/>
                    <BottomNavigationAction label="我的" value='me' icon={<AccountCircle/>}/>
                </BottomNavigation>

            </div>
        );
    }
}

export default App;

When i use method everything is normal

import './App.css';
import React from "react";
import {BottomNavigation, BottomNavigationAction} from "@material-ui/core";
import {AccountCircle, Home, Info} from "@material-ui/icons";
import makeStyles from "@material-ui/core/styles/makeStyles";
import Grid from "@material-ui/core/Grid";
import AppBar from "@material-ui/core/AppBar";
import Toolbar from "@material-ui/core/Toolbar";
import Typography from "@material-ui/core/Typography";
import styled from "@material-ui/core/styles/styled";


function App(props) {

    makeStyles(() => ({
        title: {
            color: "#ffffff"
        },
        toolbar: {
            background: "#3f51b5"
        },
        contents: {
            marginBottom: "100px"
        },
        bottomNavigation: {
            left: '0px',
            right: '0px',
            position: 'fixed',
            bottom: '0px',
        }
    }));
    const {classes} = props

    const MyGrid = styled(Grid)({
        marginTop: 10,
    });


    //切换标签选中的钩子
    const [value, setValue] = React.useState('home');

    //切换toolbar的钩子
    const [tbValue, setTbValue] = React.useState("主页");


    const handleChange = (event, newValue) => {
        setValue(newValue);
        console.log("switch" + newValue)
        //切换tb的字
        switch (newValue) {
            case 'home':
                setTbValue("主页");
                props.history.push('/home/user_login');
                break;
            case 'info':
                setTbValue("信息");
                props.history.push('/home/info');
                break;
            case 'me':
                setTbValue("我的");
                props.history.push('/home/me');
                break;
        }
    };


    return (
        <div>
            <AppBar position="static" style={{left: "0", right: "0"}}>
                <Toolbar className={classes.toolbar}>
                    <Typography className={classes.title}>
                        {tbValue}
                    </Typography>
                </Toolbar>
            </AppBar>

            {/*内容区*/}
            <div className={classes.contents}>
                <div>
                    <MyGrid container direction={'column'} justify={"center"}
                            alignContent={"center"}>
                        {props.children}
                    </MyGrid>
                </div>
            </div>


            <BottomNavigation className={classes.bottomNavigation}
                              value={value}
                              onChange={handleChange} showLabels>
                <BottomNavigationAction label="主页" value='home' icon={<Home/>}/>
                <BottomNavigationAction label="信息" value='info' icon={<Info/>}/>
                <BottomNavigationAction label="我的" value='me' icon={<AccountCircle/>}/>
            </BottomNavigation>

        </div>
    );
}

export default App;

bestphc
  • 38
  • 4
  • 3
    react-hook is for the functional component. refer to this - https://reactjs.org/docs/hooks-intro.html – wangdev87 Dec 21 '20 at 13:12
  • 3
    The error is pretty clear, react hooks are only meant to be used in function components. – Jorge Guerreiro Dec 21 '20 at 13:13
  • react-hook doesn't work on class component you can change the class component to functional component. – TinsG Dec 21 '20 at 13:15
  • Does this answer your question? [Invalid hook call. Hooks can only be called inside of the body of a function component](https://stackoverflow.com/questions/56663785/invalid-hook-call-hooks-can-only-be-called-inside-of-the-body-of-a-function-com) – Dupocas Dec 21 '20 at 13:15

1 Answers1

1

Using hooks in class component is not allowed. As stated in the react docs:

You can’t use Hooks inside a class component, but you can definitely mix classes and function components with Hooks in a single tree. Whether a component is a class or a function that uses Hooks is an implementation detail of that component. In the longer term, we expect Hooks to be the primary way people write React components.

Link: https://reactjs.org/docs/hooks-faq.html#should-i-use-hooks-classes-or-a-mix-of-both

Sagar Shakya
  • 635
  • 3
  • 7
  • But I want to use props.history.push('/home/user_login') to switch the route, and I cannot get the push method in the method component – bestphc Dec 21 '20 at 13:23
  • @bestphc you can! Check out the react-router hooks: https://reactrouter.com/native/api/Hooks/usehistory And then you can use `import { useHistory } from 'react-router-dom';` and in your method `const history = useHistory();` and then in your function `history.push('...')` – Antonio Erdeljac Dec 21 '20 at 13:54
  • Also, you should accept this answer, Sagar is correct. – Antonio Erdeljac Dec 21 '20 at 13:55
  • @Antonio Erdeljac You solved my problem perfectly, thank you so much – bestphc Dec 21 '20 at 14:07