最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Why does a useCallback option have to be called with a class component in Reactjs? - Stack Overflow

programmeradmin4浏览0评论

I am stumped. I have been trying to get a simple cleartext button to work. I have tried all the option available on this platform but nothing is working for me. React Hook useCallback cannot be called in a class ponent. React Hooks must be called in a React function ponent or a custom React Hook. I have no idea why this error is occurring. I am pretty new to react can anyone please help? I am trying to clear the text on a click of the clear button.

import React, { Component, useCallback, useState  } from "react";


import {
  Button,
  Input,
  Footer,
  Card,
  CardBody,
  CardImage,
  CardTitle,
  CardText
} from "mdbreact";

import blankImg from "./blank.gif";

import "./style.css";
import "./flags.min.css";

import countriesList from "./countries.json";

class App extends Component {
  state = {
    search: ""
  };

  renderCountry = country => {
    const { search } = this.state;
    var code = country.code.toLowerCase();

    const handleClick = useCallback(() => {
      e.target.value = '';
    }, []);
   
    return (
      <div className="col-md-3" style={{ marginTop: "20px" }}>
        <Card>
          <CardBody>
            <p className="">
              <img
                src={blankImg}
                className={"flag flag-" + code}
                alt={country.name}
              />
            </p>
            <CardTitle title={country.name}>
              {country.name.substring(0, 15)}
              {country.name.length > 15 && "..."}
            </CardTitle>
          </CardBody>
        </Card>
      </div>
    );
  };

  onchange = e => {
    this.setState({ search: e.target.value });
  };
  
  

  render() {
    const { search } = this.state;
    const filteredCountries = countriesList.filter(country => {
      return country.name.toLowerCase().indexOf(search.toLowerCase()) !== -1;
    });
   

    return (
      <div className="flyout">
        <main style={{ marginTop: "4rem" }}>
          <div className="container">
            <div className="row">
             
              <div className="col">
                <Input
                  label="Search Country"
                  icon="search"
                  onChange={this.onchange}
                />
                <button onClick={handleClick}> Click to clear</button>
              </div>
              <div className="col" />
            </div>
            <div className="row">
              {filteredCountries.map(country => {
                return this.renderCountry(country);
              })}
            </div>
          </div>
        </main>
        <Footer color="indigo">
          <p className="footer-copyright mb-0">
            &copy; {new Date().getFullYear()} Copyright
          </p>
        </Footer>
      </div>
    );
  }
}

export default App;

I am stumped. I have been trying to get a simple cleartext button to work. I have tried all the option available on this platform but nothing is working for me. React Hook useCallback cannot be called in a class ponent. React Hooks must be called in a React function ponent or a custom React Hook. I have no idea why this error is occurring. I am pretty new to react can anyone please help? I am trying to clear the text on a click of the clear button.

import React, { Component, useCallback, useState  } from "react";


import {
  Button,
  Input,
  Footer,
  Card,
  CardBody,
  CardImage,
  CardTitle,
  CardText
} from "mdbreact";

import blankImg from "./blank.gif";

import "./style.css";
import "./flags.min.css";

import countriesList from "./countries.json";

class App extends Component {
  state = {
    search: ""
  };

  renderCountry = country => {
    const { search } = this.state;
    var code = country.code.toLowerCase();

    const handleClick = useCallback(() => {
      e.target.value = '';
    }, []);
   
    return (
      <div className="col-md-3" style={{ marginTop: "20px" }}>
        <Card>
          <CardBody>
            <p className="">
              <img
                src={blankImg}
                className={"flag flag-" + code}
                alt={country.name}
              />
            </p>
            <CardTitle title={country.name}>
              {country.name.substring(0, 15)}
              {country.name.length > 15 && "..."}
            </CardTitle>
          </CardBody>
        </Card>
      </div>
    );
  };

  onchange = e => {
    this.setState({ search: e.target.value });
  };
  
  

  render() {
    const { search } = this.state;
    const filteredCountries = countriesList.filter(country => {
      return country.name.toLowerCase().indexOf(search.toLowerCase()) !== -1;
    });
   

    return (
      <div className="flyout">
        <main style={{ marginTop: "4rem" }}>
          <div className="container">
            <div className="row">
             
              <div className="col">
                <Input
                  label="Search Country"
                  icon="search"
                  onChange={this.onchange}
                />
                <button onClick={handleClick}> Click to clear</button>
              </div>
              <div className="col" />
            </div>
            <div className="row">
              {filteredCountries.map(country => {
                return this.renderCountry(country);
              })}
            </div>
          </div>
        </main>
        <Footer color="indigo">
          <p className="footer-copyright mb-0">
            &copy; {new Date().getFullYear()} Copyright
          </p>
        </Footer>
      </div>
    );
  }
}

export default App;

Share Improve this question edited Sep 8, 2021 at 11:03 Penny Liu 17.6k5 gold badges86 silver badges108 bronze badges asked Jan 22, 2021 at 13:31 brosbros 3291 gold badge5 silver badges15 bronze badges 6
  • 4 "React Hook "useCallback" cannot be called in a class ponent" - Error message is prettry self-explanatory. You can't use hooks in class ponents. – Yousaf Commented Jan 22, 2021 at 13:32
  • Basically, what you have to do is to move the renderCountry outside the App class ponent and put it into its own functional ponent, if you want to use the React hooks you are using. – secan Commented Jan 22, 2021 at 13:35
  • Is there any other way to do this other than react hooks? @secan – bros Commented Jan 22, 2021 at 13:38
  • You don't need useCallback or something similar in class ponents. – Yousaf Commented Jan 22, 2021 at 13:40
  • 1 Where is e declared? Considering the content of the function you can move it pletely out of the class, as a standalone utility function. Then you don't get any issues with references, as it is always the same function. Wait a moment, shouldn't is be handleClick = () => { this.setState({ search: ""}); } – Thomas Commented Jan 22, 2021 at 13:51
 |  Show 1 more ment

3 Answers 3

Reset to default 1

useCallback hooks can only be used in functional ponents OR in a custom Hook NOT in class ponents.

You have declared your App ponent in class based approach i.e. Object oriented approach. To use useCallback hook for this, you should change your App ponent declaration to a functional ponent or Custom hook.

Something like this

function App() {
    return (
       <>Hello World!</>
    );
}

you cannot useCallBack hook in class Component,we can do a simple thing to clear the button text, by using a button text state, i.e. { btnTxt: "Clear ButtonText"} than update the state onclick

import React, { Component, useCallback, useState  } from "react";


import {
  Button,
  Input,
  Footer,
  Card,
  CardBody,
  CardImage,
  CardTitle,
  CardText
} from "mdbreact";

import blankImg from "./blank.gif";

import "./style.css";
import "./flags.min.css";

import countriesList from "./countries.json";

class App extends Component {
  state = {
    search: "",
    btnTxt: "Clear ButtonText"
  };

  renderCountry = country => {
    const { search } = this.state;
    var code = country.code.toLowerCase();

   
    return (
      <div className="col-md-3" style={{ marginTop: "20px" }}>
        <Card>
          <CardBody>
            <p className="">
              <img
                src={blankImg}
                className={"flag flag-" + code}
                alt={country.name}
              />
            </p>
            <CardTitle title={country.name}>
              {country.name.substring(0, 15)}
              {country.name.length > 15 && "..."}
            </CardTitle>
          </CardBody>
        </Card>
      </div>
    );
  };

  onchange = e => {
    this.setState({ search: e.target.value });
  };
  
  

  render() {
    const { search } = this.state;
    const filteredCountries = countriesList.filter(country => {
      return country.name.toLowerCase().indexOf(search.toLowerCase()) !== -1;
    });
   

    return (
      <div className="flyout">
        <main style={{ marginTop: "4rem" }}>
          <div className="container">
            <div className="row">
             
              <div className="col">
                <Input
                  label="Search Country"
                  icon="search"
                  onChange={this.onchange}
                />
                <button onClick={()=>  this.setState({btnText:""})}> {this.state.btnTExt}</button>
              </div>
              <div className="col" />
            </div>
            <div className="row">
              {filteredCountries.map(country => {
                return this.renderCountry(country);
              })}
            </div>
          </div>
        </main>
        <Footer color="indigo">
          <p className="footer-copyright mb-0">
            &copy; {new Date().getFullYear()} Copyright
          </p>
        </Footer>
      </div>
    );
  }
}

export default App;

It is because you try to use hooks in a class based ponent. You can only use hooks like useCallback in functional ponents. Therefore you are mixing the concepts of object oriented and functional programming.

The following should do the trick:

import React, { Component, useCallback, useState  } from "react";


import {
  Button,
  Input,
  Footer,
  Card,
  CardBody,
  CardImage,
  CardTitle,
  CardText
} from "mdbreact";

import blankImg from "./blank.gif";

import "./style.css";
import "./flags.min.css";

import countriesList from "./countries.json";

class App extends Component {
  state = {
    search: ""
  };

   const handleClick = (e) => {
      e.target.value = '';
    };

  renderCountry = country => {
    const { search } = this.state;
    var code = country.code.toLowerCase();

    
   
    return (
      <div className="col-md-3" style={{ marginTop: "20px" }}>
        <Card>
          <CardBody>
            <p className="">
              <img
                src={blankImg}
                className={"flag flag-" + code}
                alt={country.name}
              />
            </p>
            <CardTitle title={country.name}>
              {country.name.substring(0, 15)}
              {country.name.length > 15 && "..."}
            </CardTitle>
          </CardBody>
        </Card>
      </div>
    );
  };

  onchange = e => {
    this.setState({ search: e.target.value });
  };
  
  

  render() {
    const { search } = this.state;
    const filteredCountries = countriesList.filter(country => {
      return country.name.toLowerCase().indexOf(search.toLowerCase()) !== -1;
    });
   

    return (
      <div className="flyout">
        <main style={{ marginTop: "4rem" }}>
          <div className="container">
            <div className="row">
             
              <div className="col">
                <Input
                  label="Search Country"
                  icon="search"
                  onChange={this.onchange}
                />
                <button onClick={this.handleClick}> Click to clear</button>
              </div>
              <div className="col" />
            </div>
            <div className="row">
              {filteredCountries.map(country => {
                return this.renderCountry(country);
              })}
            </div>
          </div>
        </main>
        <Footer color="indigo">
          <p className="footer-copyright mb-0">
            &copy; {new Date().getFullYear()} Copyright
          </p>
        </Footer>
      </div>
    );
  }
}

export default App;
发布评论

评论列表(0)

  1. 暂无评论