【问题标题】:Invalid hook call. Hooks can only be called inside of the body of a function component无效的挂钩调用。 Hooks 只能在函数组件的主体内部调用
【发布时间】:2019-11-01 23:08:31
【问题描述】:

我想使用 React 在表格中显示一些记录,但我收到了这个错误:

无效的挂钩调用。 Hooks 只能在 a 的主体内部调用 功能组件。这可能发生在以下情况之一 原因:

  1. 您的 React 和渲染器版本可能不匹配(例如 React DOM)
  2. 您可能违反了 Hooks 规则
  3. 您可能在同一个应用程序中拥有多个 React 副本 有关如何调试和 解决这个问题。
import React, {
  Component
} from 'react';
import {
  makeStyles
} from '@material-ui/core/styles';
import Table from '@material-ui/core/Table';
import TableBody from '@material-ui/core/TableBody';
import TableCell from '@material-ui/core/TableCell';
import TableHead from '@material-ui/core/TableHead';
import TableRow from '@material-ui/core/TableRow';
import Paper from '@material-ui/core/Paper';

const useStyles = makeStyles(theme => ({
  root: {
    width: '100%',
    marginTop: theme.spacing(3),
    overflowX: 'auto',
  },
  table: {
    minWidth: 650,
  },
}));

class allowance extends Component {
  constructor() {
    super();
    this.state = {
      allowances: [],
    };

  }

  componentWillMount() {
    fetch('http://127.0.0.1:8000/allowances')
      .then(data => {

        return data.json();

      }).then(data => {

        this.setState({
          allowances: data
        });

        console.log("allowance state", this.state.allowances);
      })

  }



  render() {
    const classes = useStyles();
    return ( <
      Paper className = {
        classes.root
      } >
      <
      Table className = {
        classes.table
      } >
      <
      TableHead >
      <
      TableRow >
      <
      TableCell > Allow ID < /TableCell> <
      TableCell align = "right" > Description < /TableCell> <
      TableCell align = "right" > Allow Amount < /TableCell> <
      TableCell align = "right" > AllowType < /TableCell>

      <
      /TableRow> <
      /TableHead> <
      TableBody > {
        this.state.allowances.map(row => ( <
          TableRow key = {
            row.id
          } >
          <
          TableCell component = "th"
          scope = "row" > {
            row.AllowID
          } <
          /TableCell> <
          TableCell align = "right" > {
            row.AllowDesc
          } < /TableCell> <
          TableCell align = "right" > {
            row.AllowAmt
          } < /TableCell> <
          TableCell align = "right" > {
            row.AllowType
          } < /TableCell>                     <
          /TableRow>
        ))
      } <
      /TableBody> <
      /Table> <
      /Paper>
    );
  }

}

export default allowance;

【问题讨论】:

    标签: javascript reactjs react-hooks material-ui


    【解决方案1】:

    就我而言,只是我的 App.js 上的这一行代码导致了这种情况,让我在调试中损失了 10 个小时。 React Native 和 Expo 无法指出这一点。我做了 StackOverflow 和 github 上的所有事情,甚至是应该解决这个问题的反应页面,但问题仍然存在。我不得不开始一点一点地拆开我的代码才能找到罪魁祸首

     **const window = useWindowDimensions();**
    

    它是这样放置的:

    import * as React from 'react';
    import { Text, View, StyleSheet, ImageBackground, StatusBar, Image, Alert, SafeAreaView, Button, TouchableOpacity, useWindowDimensions } from 'react-native';
    import Constants from 'expo-constants';
    
    import Whooksplashscreen11 from './Page1';
    import Screen1 from './LoginPage';
    import Loginscreen from './Login';
    import RegisterScreen1 from './register1';
    import RegisterScreen2 from './register2-verifnum';
    import RegisterScreen3 from './register3';
    import RegisterScreen4 from './register4';
    import RegisterScreen5 from './register5';
    import RegisterScreen6 from './register6';
    import BouncyCheckbox from "react-native-bouncy-checkbox";
    import LocationPermission from './LocationPermission.js'
    import Selfieverif1 from './selfieverif1'
    import Selfieverif2 from './selfieverif2'
    import AddPhotos from './addphotos'
    
    
    // You can import from local files
    import { useFonts } from 'expo-font';
    
    // or any pure javascript modules available in npm
    
    import { NavigationContainer } from '@react-navigation/native';
    import { createNativeStackNavigator } from '@react-navigation/native-stack';
    
    
    //FontAwesome
    import { library } from '@fortawesome/fontawesome-svg-core'
    import { fab, } from '@fortawesome/free-brands-svg-icons'
    import { faCheckSquare, faCoffee, faFilter, faSearch,  } from '@fortawesome/free-solid-svg-icons'
    import { FontAwesomeIcon } from '@fortawesome/react-native-fontawesome'
    import Icon  from "react-native-vector-icons/FontAwesome5";
    
    import MyTabs from './swipepage'
    
    library.add(fab, faCheckSquare, faCoffee, faFilter, faSearch,);
    
    
    const window = useWindowDimensions();
    const Stack = createNativeStackNavigator();
    
    function App() {
      return ( ....
    )}
    

    【讨论】:

      【解决方案2】:

      你只能从 React 函数调用钩子。阅读更多here

      只需将Allowance 类组件转换为函数式组件即可。

      Working CodeSandbox demo.

      const Allowance = () => {
        const [allowances, setAllowances] = useState([]);
      
        useEffect(() => {
          fetch("http://127.0.0.1:8000/allowances")
            .then(data => {
              return data.json();
            })
            .then(data => {
              setAllowances(data);
            })
            .catch(err => {
              console.log(123123);
            });
        }, []);
      
        const classes = useStyles();
        return ( <
          Paper className = {
            classes.root
          } >
          <
          Table className = {
            classes.table
          } >
          <
          TableHead >
          <
          TableRow >
          <
          TableCell > Allow ID < /TableCell> <
          TableCell align = "right" > Description < /TableCell> <
          TableCell align = "right" > Allow Amount < /TableCell> <
          TableCell align = "right" > AllowType < /TableCell> <
          /TableRow> <
          /TableHead> <
          TableBody > {
            allowances.map(row => ( <
              TableRow key = {
                row.id
              } >
              <
              TableCell component = "th"
              scope = "row" > {
                row.AllowID
              } <
              /TableCell> <
              TableCell align = "right" > {
                row.AllowDesc
              } < /TableCell> <
              TableCell align = "right" > {
                row.AllowAmt
              } < /TableCell> <
              TableCell align = "right" > {
                row.AllowType
              } < /TableCell> <
              /TableRow>
            ))
          } <
          /TableBody> <
          /Table> <
          /Paper>
        );
      };
      
      export default Allowance;
      

      【讨论】:

      • 有一件事想问你,调用setAllowances(data)后,津贴应该有数据吧?否则,配额什么时候有数据?
      • 是的。在调用 setAllowances(data) 之后。 setAllowancesthis.setState({allowances: data}) 一样工作
      • 我有点糊涂,在调用setAllowances(data)之后,我试试console.log("data",data);这有 3 条记录,但如果我尝试使用 console.log("allowance",allowances);这没什么记录。我可以知道为什么吗?您可以在代码示例中尝试。
      • 因为 setAllowances 像 this.setState 一样是异步的。所以你在setAllowances之后记录allowances,它会记录old allowances
      • 作者的零用钱在哪里?
      【解决方案3】:

      当您遇到此问题时,您只需重新安装此“npm install react-bootstrap@next bootstrap@5.1.0”即可解决您的错误。

      【讨论】:

      • 这并不能真正回答问题。如果您有其他问题,可以点击 提问。要在此问题有新答案时收到通知,您可以follow this question。一旦你有足够的reputation,你也可以add a bounty 来引起更多的关注。
      【解决方案4】:

      注意导入问题-对我来说,错误是关于组件和子组件的导入/自动导入失败。与功能类与类组件无关。

      • 这很容易发生,因为 VS 代码自动导入可以指定不起作用的路径。
      • 如果使用了 import { MyComponent } 并且在组件中使用了 export default,则导入应该是 import MyComponent
      • 如果某些组件在其文件夹中使用 index.js 作为路径的快照,而其他不是导入的组件可能会中断。这里再次自动导入可能会导致问题,因为它将所有组件合并到与此 {TextComponent, ButtonComponent, ListComponent} from '../../common' 相同的文件夹中

      尝试注释掉文件中给出错误的一些组件,您可以测试是否是问题所在。

      【讨论】:

        【解决方案5】:

        您可以检查您的路线。如果您在 Route(} />) 中使用渲染而不是组件 所以你在一个箭头函数中正确地调用了你的组件,并将适当的道具传递给它。

        【讨论】:

          【解决方案6】:

          如果你使用 react-router-dom,请确保在钩子中调用 useHistory()。

          【讨论】:

            【解决方案7】:

            就我而言,我在 package-json 中所做的更改会导致问题。

            npm install react-redux
            

            解决这个问题

            【讨论】:

              【解决方案8】:

              就我而言,我从两个项目中删除了 package-lock.jsonnode_modules 并再次重新安装,现在可以正常工作了。

              
              // project structure
              
              
              root project
              - package-lock.json
              - package.json // all dependencies are installed here
              - node_modules
              
              -- second project
              -- package-lock.json
              -- package.json 
                "dependencies": {
                  "react": "file:../node_modules/react",
                  "react-dom": "file:../node_modules/react-dom",
                  "react-scripts": "file:../node_modules/react-scripts"
                },
              -- node_modules
              
              
              

              不知道是什么原因导致了这个问题,因为我以前也遇到过这种情况,按照上面的步骤做了,问题就解决了。

              【讨论】:

                【解决方案9】:

                就我而言,我在FlatListrenderItem 属性中传递了组件名称,而不是函数。因为我的组件是一个函数式组件,所以它之前可以工作,但是当我在其中添加钩子时,它失败了。

                之前:

                    <FlatList
                        data={memberList}
                        renderItem={<MemberItem/>}
                        keyExtractor={member => member.name.split(' ').join('')}
                        ListEmptyComponent={
                          <Text style={{textAlign: 'center', padding: 30}}>
                            No Data: Click above button to fetch data
                          </Text>
                        }
                      />
                

                之后:

                    <FlatList
                        data={memberList}
                        renderItem={({item, index}) => <MemberItem item={item} key={index} />}
                        keyExtractor={member => member.name.split(' ').join('')}
                        ListEmptyComponent={
                          <Text style={{textAlign: 'center', padding: 30}}>
                            No Data: Click above button to fetch data
                          </Text>
                        }
                      />
                

                【讨论】:

                  【解决方案10】:

                  这是为我解决的问题。我的组件文件夹以及它所属的项目的根目录中有文件夹 node_modules 和文件 package.json 和 package-lock.json。我从它们不属于的地方删除了它们。不要问我做了什么把它们放在那里,我一定是从错误的位置做了一个 npm 的东西。

                  【讨论】:

                    【解决方案11】:

                    我遇到这个问题,我的错误原因是我开发项目A并将另一个项目B链接到A,但是A有React包,B也有React包,它们是相同的版本(16.13)。 但这引起了问题,我设置文件意味着webpack.config.js,像这样:

                    alias: {
                      'react': path.join(path.resolve(__dirname), '../node_modules/react'),
                    },
                    

                    set B React package resolve to A React package,我猜原因是一个项目不能有两个或多个 React 包,即使它们是相同的版本。但我无法验证我的猜测。

                    【讨论】:

                      【解决方案12】:

                      致任何可能寻求快速解决此问题的人:

                      您可能违反了 Hooks 规则。 为了解决这个问题,移动:

                      ?const [x, setX] = useState(0);
                      

                      到调用它的函数的顶层而不是函数之外。

                      function App() {
                         ?const [t, setTime] = useState("");
                      
                         return (
                            <div>
                               <h1>{x}</h1>
                               <button onClick={() => setTime(x+1)}>Get Time</button>
                            </div>
                       );
                      }
                      

                      ? https://reactjs.org/warnings/invalid-hook-call-warning.html

                      【讨论】:

                      【解决方案13】:

                      将此添加到您的 package.json 中

                      "peerDependencies": {
                         "react": ">=16.8.0",
                         "react-dom": ">=16.8.0"
                      }
                      

                      来源:https://robkendal.co.uk/blog/2019-12-22-solving-react-hooks-invalid-hook-call-warning

                      【讨论】:

                        【解决方案14】:

                        如果您使用的是 mobx,并且您的功能组件包装在 mobx observer 函数中,也会出现此错误。如果是这种情况,请确保您使用的是 mobx-react 6.0.0 或更高版本。旧版本会将您的功能组件转换为隐藏的类,并且所有挂钩都将因此错误而失败。

                        在此处查看答案:React Hooks Mobx: invalid hook call. Hooks can only be called inside of the body of a function component

                        【讨论】:

                          【解决方案15】:

                          当我使用npm link 安装我使用cra 构建的本地库时遇到了这个问题。我找到了答案here。字面意思是:

                          当您使用 npm link 或等效项时,也会出现此问题。 在这种情况下,你的打包器可能会“看到”两个 React——一个在应用程序中 文件夹和一个在您的库文件夹中。假设“myapp”和“mylib” 是同级文件夹,一种可能的解决方法是运行 'npm link ../myapp/node_modules/react' 来自“mylib”。这应该使 库使用应用程序的 React 副本。

                          因此,运行命令:npm link &lt;path_to_local_library&gt;/node_modules/react,例如。就我而言,项目目录中的npm link ../../libraries/core/decipher/node_modules/react 已解决此问题。

                          【讨论】:

                          • 谢谢伙计!你救了我的一天!所有通过 npm/yarn 链接使用本地包的人,请关注这个!
                          • 这对我有用。这是我的确切问题。
                          • 那么在npm上发布会报错吧?或者可能没有,因为它是链接的,在我的机器上它将使用来自链接的反应,并且在发布后,它将使用它自己的。 ?
                          • 长时间使用链接到本地​​库的cra 处理应用程序,我永远不会看到此错误消息。只需在两个项目上运行npm i,然后再次运行npm link,就可以了。
                          • 我花了 8 个小时解决这个问题,并试图以不同的方式完成该功能。非常感谢
                          【解决方案16】:

                          我的共享库之间的不同版本的 react 似乎是问题(16 和 17),都更改为 16。

                          【讨论】:

                            【解决方案17】:

                            当您使用依赖项而不安装它时也会发生这种情况。 当我从“@material-ui/icons/”调用 MenuIcon 时发生在我身上,而该项目中缺少该图标。

                            【讨论】:

                              【解决方案18】:

                              complementing the following comment

                              对于那些使用 redux 的人:

                              class AllowanceClass extends Component{
                                  ...
                                  render() {
                                      const classes = this.props.classes;
                                      ...
                                  }
                              }
                                  
                              const COMAllowanceClass = (props) =>
                              {
                                  const classes = useStyles();
                                  return (<AllowanceClass classes={classes} {...props} />);
                              };
                              
                              const mapStateToProps = ({ InfoReducer }) => ({
                                  token: InfoReducer.token,
                                  user: InfoReducer.user,
                                  error: InfoReducer.error
                              });
                              export default connect(mapStateToProps, { actions })(COMAllowanceClass);
                              

                              【讨论】:

                                【解决方案19】:

                                当你错误地从 react-redux 声明 useDispatch 时,也会出现这个错误: 去的时候:
                                const dispatch = useDispatch 而不是:
                                const dispatch = useDispatch();(即记得加括号)

                                【讨论】:

                                • 对我来说,这是关于 redux react-redux 未安装在项目级别的软件包(但存在于 monorepo 的顶层)。
                                【解决方案20】:

                                我的情况.... 解决方案在 HOOKS 中

                                const [cep, setCep] = useState('');
                                const mounted = useRef(false);
                                
                                useEffect(() => {
                                    if (mounted.current) {
                                        fetchAPI();
                                      } else {
                                        mounted.current = true;
                                      }
                                }, [cep]);
                                
                                const setParams = (_cep) => {
                                    if (cep !== _cep || cep === '') {
                                        setCep(_cep);
                                    }
                                };
                                

                                【讨论】:

                                  【解决方案21】:

                                  就我而言,我试图在 Windows 上使用 mdbreact。虽然它已安装,但我收到了上述错误。我不得不重新安装它,一切都很好。曾经两次用 antd Library 发生在我身上

                                  【讨论】:

                                  • 这对我也有帮助,我只是决定完全使用另一个 UI 库
                                  【解决方案22】:

                                  对我来说,错误是在默认导出的函数之外调用函数 useState

                                  【讨论】:

                                    【解决方案23】:

                                    遇到此错误:找到解决方案。

                                    由于某种原因,我的标签上有 2 个onClick 属性。 小心使用您或他人的自定义组件,可能其中一些已经具有onClick 属性。

                                    【讨论】:

                                      【解决方案24】:

                                      您可以通过调用一个箭头函数来使用“导出默认值”,该函数通过 MaterialUI 类对象道具传递它返回其 React.Component,而后者又将在组件渲染 () 中使用。

                                      class AllowanceClass extends Component{
                                          ...
                                          render() {
                                              const classes = this.props.classes;
                                              ...
                                          }
                                      }
                                      
                                      export default () => {
                                          const classes = useStyles();
                                          return (
                                              <AllowanceClass classes={classes} />
                                          )
                                      }
                                      

                                      【讨论】:

                                        【解决方案25】:

                                        如果以上所有方法都不起作用,特别是如果具有大尺寸依赖性(如我的情况),则构建和加载都需要至少 15 秒,因此延迟似乎给出了错误消息“无效的钩子调用。 " 所以你能做的就是在测试之前给一些时间来确保构建完成。

                                        【讨论】:

                                          【解决方案26】:

                                          我刚刚开始使用钩子,当我在函数中调用 useEffect 时收到上述警告:

                                          然后我必须将 useEffect 移到函数之外,如下所示:

                                           const onChangeRetypePassword = async value => {
                                            await setRePassword(value);
                                          //previously useEffect was here
                                          
                                            };
                                          //useEffect outside of func 
                                          
                                           useEffect(() => {
                                            if (password !== rePassword) {
                                            setPasswdMismatch(true);
                                          
                                               } 
                                            else{
                                              setPasswdMismatch(false);
                                           }
                                          }, [rePassword]);
                                          

                                          希望对某人有所帮助!

                                          【讨论】:

                                            【解决方案27】:

                                            昨天,我缩短了代码(刚刚添加了&lt;Provider store={store}&gt;),仍然遇到了这个无效的钩子调用问题。这让我突然意识到自己犯了什么错误:我没有在那个文件夹中安装 react-redux 软件。

                                            我已经在另一个项目文件夹中安装了这个软件,所以我没有意识到这个也需要它。安装后,错误消失了。

                                            【讨论】:

                                            • 你是怎么解决的?我也使用提供者游戏控制台报告我有一些关于钩子调用的错误
                                            【解决方案28】:

                                            你可以将类组件转换为钩子,但是 Material v4 有一个 withStyles HOC。 https://material-ui.com/styles/basics/#higher-order-component-api 使用此 HOC,您可以保持代码不变。

                                            【讨论】:

                                              【解决方案29】:

                                              React linter 假定每个方法都以 use 开头,因为钩子和钩子在类中不起作用。通过将const useStyles 重命名为不以use 开头的任何其他名称,例如const myStyles,您就可以开始了。

                                              更新:

                                              makeStyles 是钩子 api,你不能在类中使用它。您可以使用样式化组件 API。见here

                                              【讨论】:

                                              • 将 usestyles 更改为 mystyles 但仍然出现错误。
                                              • 是否有任何文件表明这是真的?
                                              • 是的,你是对的。 makeStyles 是钩子 api,你不能在类中使用它。见here
                                              猜你喜欢
                                              • 1970-01-01
                                              • 2019-12-12
                                              • 2022-01-25
                                              • 1970-01-01
                                              • 2021-12-18
                                              • 2020-07-22
                                              • 2020-02-24
                                              • 1970-01-01
                                              相关资源
                                              最近更新 更多