简体   繁体   English

自定义挂钩错误:只能在 function 组件的主体内部调用挂钩

[英]Custom hook error: Hooks can only be called inside of the body of a function component

I am trying to develop a custom hook which seems to be pretty easy but I am getting an error我正在尝试开发一个似乎很容易的自定义钩子,但我遇到了一个错误

Uncaught Invariant Violation: Invalid hook call.未捕获的不变违规:无效的挂钩调用。 Hooks can only be called inside of the body of a function component.钩子只能在 function 组件的主体内部调用。 This could happen for one of the following reasons:这可能由于以下原因之一而发生:

  1. You might have mismatching versions of React and the renderer (such as React DOM)你可能有不匹配的 React 版本和渲染器(例如 React DOM)
  2. You might be breaking the Rules of Hooks您可能违反了 Hooks 规则
  3. You might have more than one copy of React in the same app你可能在同一个应用程序中拥有多个 React 副本

This is my hook:这是我的钩子:

import React, { useState, useEffect } from 'react';

const useInfiniteScroll = (isLastPage: boolean, fetchFn: any) => {
  const [pageCount, setPageCount] = useState(0);
  const triggerFetchEvents = (): void => {
    let response;

    setPageCount(() => {
      if (!isLastPage) {
        response = fetchFn(pageCount + 1, 5, 'latest');
      }

      return pageCount + 1;
    });

    return response;
  };

  useEffect(() => {
    triggerFetchEvents();
  }, []);

  return pageCount;
};

export default useInfiniteScroll;

And the component here I am calling it:我在这里调用它的组件:

import React, { FC } from 'react';
import { connect } from 'react-redux';
import { fetchEvents } from '../../shared/actions/eventActions';
import { AppState } from '../../shared/types/genericTypes';
import EventModel from '../../shared/models/Event.model';
import EventListPage from '../../components/events/EventListPage';
import useInfiniteScroll from '../../shared/services/triggerInfiniteScroll';

type Props = {
  fetchEvents?: any;
  isLastPage: boolean;
  eventsList?: EventModel[];
};

const mapState: any = (state: AppState, props: Props): Props => ({
  eventsList: state.eventReducers.eventsList,
  isLastPage: state.eventReducers.isLastPage,
  ...props
});

const actionCreators = {
  fetchEvents
};

export const EventsScene: FC<Props> = props => {
  const { eventsList, fetchEvents, isLastPage } = props;
  const useIn = () => useInfiniteScroll(isLastPage, fetchEvents);

  useIn();

  // const [pageCount, setPageCount] = useState(0);

  // const triggerFetchEvents = (): void => {
  //   let response;

  //   setPageCount(() => {
  //     if (!isLastPage) {
  //       response = fetchEvents(pageCount + 1, 1, 'latest');
  //     }

  //     return pageCount + 1;
  //   });

  //   return response;
  // };

  // useEffect(() => {
  //   triggerFetchEvents();
  // }, []);

  if (!eventsList || !eventsList.length) return null;

  return (
    <EventListPage
      eventsList={eventsList}
      isLastPage={isLastPage}
      triggerFetchEvents={useIn}
    />
  );
};

export default connect(
  mapState,
  actionCreators
)(EventsScene);

I left the commented code there to show you that if I uncomment the code and remove useInfiniteScroll then it works properly.我将注释代码留在那里向您展示,如果我取消注释代码并删除useInfiniteScroll那么它可以正常工作。

What could I be missing?我会错过什么?

UPDATE: This is EventListPage component更新:这是EventListPage组件

import React, { useState, useEffect } from 'react';
import { Link } from 'react-router-dom';
import EventModel from '../../shared/models/Event.model';
import { formatDate } from '../../shared/services/date';
import Container from 'react-bootstrap/Container';
import Row from 'react-bootstrap/Row';
import Col from 'react-bootstrap/Col';
import Card from 'react-bootstrap/Card';

type Props = {
  eventsList?: EventModel[];
  isLastPage: boolean;
  triggerFetchEvents: any;
};

export const EventListPage: React.FC<Props> = props => {
  const { eventsList, triggerFetchEvents, isLastPage } = props;

  const [isFetching, setIsFetching] = useState(false);

  const fetchMoreEvents = (): Promise<void> =>
    triggerFetchEvents().then(() => {
      setIsFetching(false);
    });

  const handleScroll = (): void => {
    if (
      document.documentElement.offsetHeight -
        (window.innerHeight + document.documentElement.scrollTop) >
        1 ||
      isFetching
    ) {
      return;
    }

    return setIsFetching(true);
  };

  useEffect(() => {
    if (isFetching) return;

    window.addEventListener('scroll', handleScroll);

    return () => {
      window.removeEventListener('scroll', handleScroll);
    };
  }, []);

  useEffect(() => {
    if (!isFetching) return;

    if (!isLastPage) fetchMoreEvents();
  }, [isFetching]);

  if (!eventsList) return null;

  return (
    <Container className='article-list mt-5'>
      ///...
    </Container>
  );
};

export default EventListPage;

In EventsScene , change useInfiniteScroll to be invoked directly at the function body top-level (not sure why you are creating this indirection in the first place):EventsScene中,将useInfiniteScroll更改为直接在 function 主体顶层调用(不知道为什么首先要创建此间接):

// before
const useIn = () => useInfiniteScroll(isLastPage, fetchEvents);
useIn();

// after
useInfiniteScroll(isLastPage, fetchEvents)

React expects Hook calls to onlyhappen at the top-level as it relies on the order of Hooks to be always the same. React 期望 Hook 调用只发生在顶层,因为它依赖于 Hook 的顺序始终相同。 If you wrap the Hook in a function, you can potentially invoke this function in many code locations disturbing the Hooks' order.如果您将 Hook 包装在 function 中,您可能会在许多干扰 Hook 顺序的代码位置调用此 function。

There is an internal list of “memory cells” associated with each component.每个组件都有一个内部“存储单元”列表。 They're just JavaScript objects where we can put some data.它们只是 JavaScript 对象,我们可以在其中放置一些数据。 When you call a Hook like useState(), it reads the current cell (or initializes it during the first render), and then moves the pointer to the next one.当你调用 useState() 之类的 Hook 时,它会读取当前单元格(或在第一次渲染期间对其进行初始化),然后将指针移动到下一个单元格。 This is how multiple useState() calls each get independent local state.这就是多个 useState() 调用各自获得独立本地 state 的方式。 Link 关联

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 如何修复 React 自定义挂钩中的“只能在 function 组件的主体内调用挂钩”错误? - How to fix 'Hooks can only be called inside the body of a function component' error in React custom hook? 反应钩子错误:无效的钩子调用。 钩子只能在 function 组件的主体内部调用 - React hook Error: Invalid hook call. Hooks can only be called inside of the body of a function component 导入异步 function 错误:挂钩调用无效。 钩子只能在 function 组件的内部调用 - Importing async function error: Invalid hook call. Hooks can only be called inside of the body of a function component 错误消息:未捕获错误:无效挂钩调用。 钩子只能在 function 组件的内部调用 - Error Message: Uncaught Error: Invalid hook call. Hooks can only be called inside of the body of a function component 错误。 错误:无效挂钩调用。 钩子只能在 function 组件的内部调用 - Error. Error: Invalid hook call. Hooks can only be called inside of the body of a function component 我不断收到:错误:无效的挂钩调用。 Hooks 只能在函数组件内部调用 - I keep getting:Error: Invalid hook call. Hooks can only be called inside of the body of a function component 未捕获的错误:无效的挂钩调用。 钩子只能在函数组件的主体内部调用吗? - Uncaught Error: Invalid hook call. Hooks can only be called inside of the body of a function component? 挂钩调用错误:只能在 function 组件的主体内部调用挂钩 - hook call error: Hooks can only be called inside of the body of a function component React 17:错误:无效的钩子调用。 钩子只能在 function 组件的主体内部调用 - React 17: Error: Invalid hook call. Hooks can only be called inside of the body of a function component React Native:错误:无效的挂钩调用。 钩子只能在 function 组件的主体内部调用 - React Native: Error: Invalid hook call. Hooks can only be called inside of the body of a function component
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM