【问题标题】:React Hooks - Invalid Hook CallReact Hooks - 无效的 Hook 调用
【发布时间】:2021-03-01 09:28:02
【问题描述】:

我遇到了一个错误

Error: Invalid hook call. Hooks can only be called inside of the body of a function component. This could happen for one of the following reasons:
1. You might have mismatching versions of React and the renderer (such as React DOM)
2. You might be breaking the Rules of Hooks
3. You might have more than one copy of React in the same app

这是我的钩子useParking:

import { Strings } from "..";
import { get } from "../HTTPProvider";
import { Lot } from ".";
import { Moment } from "moment";
import L from "leaflet";

interface ApiResponse {
  id: string;
  fields: Lot;
  createdTime: Moment | string;
}

const { apiUrl, apiKey } = Strings;
const [error, setError] = useState(false);

const getParkingLots = (setParkingLots: (l: Lot[]) => void) => {
  get<{ records: ApiResponse[] }>(`${apiUrl}Parking%20Lots`, { apiKey })
    .then((response) => {
      console.log(response);
      const data: Lot[] = [];

      response.data.records.forEach((record) => {
        const lat = record.fields.latitude;
        const lon = record.fields.longitude;

        if (lat && lon) record.fields.coordinates = L.latLng([lat, lon]);
        data.push(record.fields);
      });
      setParkingLots(data);
    })
    .catch((error) => setError(error));
  console.log(error);
};

export const useParkingLot = (): Lot[] => {
  const [parkingLots, setParkingLots] = useState<Lot[]>([]);

  useEffect(() => {
    getParkingLots(setParkingLots);
  }, [parkingLots]);

  return parkingLots;
};

我正在尝试在我的MainTabs 组件中使用钩子:

import {
  IonTabs,
  IonTabBar,
  IonTabButton,
  IonIcon,
  IonLabel,
  IonRouterOutlet,
} from "@ionic/react";
import { map, business, calendarOutline, carOutline } from "ionicons/icons";
import { Route, Redirect } from "react-router";
import { CampusMap, Events, Buildings, ParkingLots } from "../../pages";
import { useFakeEvent } from "../../DataProviders";
import { useBuilding } from "../../DataProviders";
import { useParkingLot } from "../../DataProviders";

export const MainTabs: React.FC = () => {
  const buildings = useBuilding();
  const parkingLots = useParkingLot();
  const [events, setEvents] = useState(useFakeEvent());
  const [showName, setShowName] = useState(true);

  const toggleName = () => {
    console.log("resetName called");
    setShowName(false);
    return setTimeout(() => {
      setShowName(true);
    });
  };

  return (
    <IonTabs>
      <IonRouterOutlet>
        <Route path="/:tab(Events)" render={() => <Events />} exact={true} />
        <Route
          path="/:tab(Map)"
          render={() => (
            <CampusMap
              buildings={buildings}
              showName={showName}
              parkingLots={parkingLots}
              events={events}
            />
          )}
          exact={true}
        />
        <Route
          path="/:tab(BuildingList)"
          render={() => <Buildings buildings={buildings} />}
          exact={true}
        />
        <Route
          path="/:tab(ParkingLotList)"
          render={() => <ParkingLots parkingLots={parkingLots} />}
          exact={true}
        />
        <Route exact path="/" render={() => <Redirect to="/Map" />} />
      </IonRouterOutlet>

      <IonTabBar slot="bottom">
        <IonTabButton tab="Map" href="/Map" onClick={toggleName}>
          <IonIcon icon={map} />
          <IonLabel>Map</IonLabel>
        </IonTabButton>

        <IonTabButton tab="BuildingList" href="/BuildingList">
          <IonIcon icon={business} />
          <IonLabel>Buildings</IonLabel>
        </IonTabButton>

        <IonTabButton tab="Events" href="/Events">
          <IonIcon icon={calendarOutline} />
          <IonLabel>Events</IonLabel>
        </IonTabButton>

        <IonTabButton tab="ParkingList" href="/ParkingLotList">
          <IonIcon icon={carOutline} />
          <IonLabel>Parking Lots</IonLabel>
        </IonTabButton>
      </IonTabBar>
    </IonTabs>
  );
};

我已经根据 Hook 文档规则检查了我的代码,但我似乎没有违反任何规则。我还检查了我的依赖项,他们都签了。所以我不确定为什么我会收到错误消息。谁能看到我在这里做错了什么?

【问题讨论】:

  • 你在getParkingLots上方的顶层使用了一个钩子。钩子调用必须在一个组件或另一个钩子中。
  • const [error, setError] = useState(false); 需要位于功能组件主体或自定义挂钩中。
  • 这能回答你的问题吗? Why am I making an invalid hook call?
  • Drew Reese 的评论回答了我的问题。有没有办法让我选择他的评论作为接受的答案?

标签: reactjs typescript react-native react-hooks use-state


【解决方案1】:

getParkingLots 函数内部使用useState,因为您在导致Invalid Hook Call 的函数组件外部定义了useState。尝试在里面初始化

const getParkingLots = (setParkingLots: (l: Lot[]) => void) => {
  const [error, setError] = useState(false); // here 
  get<{ records: ApiResponse[] }>(`${apiUrl}Parking%20Lots`, { apiKey })
    .then((response) => {
      ....
    })
    .catch((error) => setError(error));
  console.log(error);
};

【讨论】:

    【解决方案2】:

    const [error, setError] = useState(false);需要在功能组件主体或自定义钩子中。 ——德鲁里斯

    这修正了错误。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-02-12
      • 2020-08-02
      • 1970-01-01
      • 2023-02-14
      • 1970-01-01
      • 2020-03-08
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多