【问题标题】:Unable to use useState in class component React.js无法在类组件 React.js 中使用 useState
【发布时间】:2020-03-31 22:44:36
【问题描述】:

我正在尝试在 react 中创建常量,如下所示:

const [firstFocus, setFirstFocus] = React.useState(false);
const [lastFocus, setLastFocus] = React.useState(false);

代码中使用的常量如下:

import React, { Component } from 'react'
import axios from 'axios'

import {
    Button,
    Card,
    CardHeader,
    CardBody,
    CardFooter,
    Form,
    Input,
    InputGroupAddon,
    InputGroupText,
    InputGroup,
    Container,
    Col
} from "reactstrap";

class PostForm extends Component {
    constructor(props) {
        super(props)

        this.state = {
            email: '',
            password: ''
        }
    }

    changeHandler = (e) => {
        this.setState({ [e.target.name]: e.target.value })
    }

    submitHandler = (e) => {
        e.preventDefault()
        console.log(this.state)
        axios.post('https://jsonplaceholder.typicode.com/posts', this.state)
            .then(response => {
                console.log(response)
            })
            .catch(error => {
                console.log(error)
            })
    }


    render() {
        const { email, password } = this.state
        **const [firstFocus, setFirstFocus] = React.useState(false);
        const [lastFocus, setLastFocus] = React.useState(false);**
        return (

            <div>
                <Col className="ml-auto mr-auto" md="4">
                    <Card className="card-login card-plain">
                        <Form onSubmit={this.submitHandler} className="form">
                            <CardHeader className="text-center">
                            </CardHeader>
                            <CardBody>
                                <InputGroup
                                    className={
                                        "no-border input-lg"
                                    }
                                >
                                    <InputGroupAddon addonType="prepend">
                                        <InputGroupText>
                                            <i className="now-ui-icons ui-1_email-85"></i>
                                        </InputGroupText>
                                    </InputGroupAddon>
                                    <Input
                                        placeholder="Email"
                                        type="text"
                                        name="email"
                                        value={email}
                                        onChange={this.changeHandler}
                                    // onFocus={() => setFirstFocus(true)}
                                    // onBlur={() => setFirstFocus(false)}
                                    ></Input>
                                </InputGroup>
                                <InputGroup
                                    className={
                                        "no-border input-lg"
                                    }
                                >
                                    <InputGroupAddon addonType="prepend">
                                        <InputGroupText>
                                            <i className="now-ui-icons ui-1_lock-circle-open"></i>
                                        </InputGroupText>
                                    </InputGroupAddon>
                                    <Input
                                        placeholder="Password"
                                        type="password"
                                        name="password"
                                        value={password}
                                        onChange={this.changeHandler}
                                    // onFocus={() => setLastFocus(true)}
                                    // onBlur={() => setLastFocus(false)}
                                    ></Input>
                                </InputGroup>
                            </CardBody>
                            <CardFooter className="text-center">
                                <Button
                                    block
                                    className="btn-round"
                                    color="info"
                                    type="submit"
                                    size="lg"
                                >
                                    Get Started
                    </Button>
                                <div className="pull-right">
                                    <h6>
                                        <a
                                            className="link"
                                            href="#pablo"
                                            onClick={e => e.preventDefault()}
                                        >
                                            Need Help?
                        </a>
                                    </h6>
                                </div>
                            </CardFooter>
                        </Form>
                    </Card>
                </Col>
            </div>
        )
    }
}

export default PostForm

但是,当我尝试这样做时,我收到以下错误:

无效的挂钩调用。 Hooks 只能在 a 的主体内部调用 功能组件。

我在那里为电子邮件和密码创建了另一个常量,它工作得很好,所以我不确定为什么我的 useState 常量不起作用。非常感谢任何帮助或指导,因为我对反应非常陌生。谢谢!

【问题讨论】:

    标签: reactjs


    【解决方案1】:

    在 react 中,我们有 2 种方式来构建组件:类和函数。

    DOCS

    Hooks 是 React 16.8 中的新增功能。它们让您无需编写类即可使用状态和其他 React 功能。

    使用状态钩子:

    import React, { useState } from 'react';
    
    function Example() {
      // Declare a new state variable, which we'll call "count"
      const [count, setCount] = useState(0);
    
      return (
        <div>
          <p>You clicked {count} times</p>
          <button onClick={() => setCount(count + 1)}>
            Click me
          </button>
        </div>
      );
    }
    

    等效类示例:

    class Example extends React.Component {
      constructor(props) {
        super(props);
        this.state = {
          count: 0
        };
      }
    
      render() {
        return (
          <div>
            <p>You clicked {this.state.count} times</p>
            <button onClick={() => this.setState({ count: this.state.count + 1 })}>
              Click me
            </button>
          </div>
        );
      }
    }
    

    【讨论】:

      【解决方案2】:

      官方不能在类组件上使用钩子。但是,如果你想在类组件上使用 useState,当然有一些技巧

      例如,你不能这样做

      class Example extends React.Component {
      
        _renderCounter = () => {
          //
          // YOU CAN'T DO THIS
          // REACT WONT ALLOW YOU
          //
          const [count, setCount] = useState(0);
          return <div>{ count }</div>
        }
      
        render() {
          return(
            <div>{ this._renderCounter() }</div>
          );
        }
      }
      

      但是,通过小技巧,您可以做到这一点。 React 会让你

      class Example extends React.Component {
      
        _renderCounter = () => () => {
          const [count, setCount] = useState(0);
      
          return <div>{ count }</div>
        }
      
        render() {
          const MyInlineHook = this._renderCounter();
      
          return(
            <div><MyInlineHook /></div>
          );
        }
      }
      

      通过这个技巧,你可以访问类组件的thisprops。 :)

      【讨论】:

      • 您如何以这种方式访问​​ setCount 方法?
      【解决方案3】:

      您正在尝试在类组件中使用 useState,它是一个 React 钩子。这行不通。 Hooks 只能用在函数式组件中。

      【讨论】:

      • 你知道类组件的等效实现/方法是什么吗?
      • 您需要在您的构造函数中创建一个名为 this.state 的状态对象。然后,您可以通过调用 this.setState 在方法中更改它。在这里解释会很长,但你可以在这里查看文档reactjs.org/docs/state-and-lifecycle.html 或谷歌在类组件中初始化状态
      【解决方案4】:

      Hooks 只能用在函数式组件中,你使用的是类组件。

      有关更多信息以及如何实施,请查看本文Link

      【讨论】:

        【解决方案5】:

        这对我有用,我刚刚声明 index 和 setIndex 如下。可能是一个肮脏的黑客,但是嘿?‍♂️

        
            render(){
              const index = this.state.index;
              const setIndex = (params) => this.setState({index: params});
              return {
                <Tab value={index} onChange={setIndex}>
                  <Tab.Item title="recent" />
                  <Tab.Item title="favorite" />
                  <Tab.Item title="cart" />
                </Tab>
        
                <TabView value={index} onChange={setIndex} >
                  <TabView.Item style={{ backgroundColor: 'red', width: '100%' }}>
                    <Text h1>recent</Text>
                  </TabView.Item>
                  <TabView.Item style={{ backgroundColor: 'blue', width: '100%' }}>
                    <Text h1>Favorite</Text>
                  </TabView.Item>
                  <TabView.Item style={{ backgroundColor: 'green', width: '100%' }}>
                    <Text h1>Cart</Text>
                  </TabView.Item>
                </TabView>
              }
            }
        

        【讨论】:

          【解决方案6】:

          另一种方法是在功能组件中使用钩子,然后将这个功能组件导入到类组件中。

          export default class LikeButton extends Component {
            render() {
              return <Like />;
            }
          }
          
          function Like() {
            const [like, setLike] = useState(100);
            const [liked, toggleLike] = useState(false);
            const handleLike = () => {
              if (liked == false) {
                setLike(like + 1);
                toggleLike(true);
              } else {
                setLike(like - 1);
                toggleLike(false);
              }
            };
            return (
              <>
                <div>
                  <h2>Like Button</h2>
                  <button
                    onClick={() => handleLike()}
                    className={`like-button ${liked == true ? "liked" : ""}`}
                  >
                    Like | <span className="likes-counter">{like}</span>
                  </button>
                </div>
              </>
            );
          }
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2019-12-03
            • 1970-01-01
            • 2021-10-03
            • 2022-01-23
            • 1970-01-01
            • 1970-01-01
            • 2019-08-10
            相关资源
            最近更新 更多