Пользовательский хук не извлекает данные, как ожидалось

Это продолжение связанного сообщения о том же общем коде. Я создал специальный хук useLUGet, предназначенный только для того, чтобы быть оболочкой для некоторых вызовов fetch/axios. Я следовал (в основном) этому репозиторию, который отлично работает сам по себе, потому что App.js инициирует вызов событием onSubmit. В моем случае я просто хочу загрузить раскрывающийся список при загрузке страницы. Пользовательский хук просто не срабатывает, и я не уверен, как это сделать, не помещая его в useEffect(()=>{...}, []) с пустым массивом, а это противоречит правилам магического хука. Я подтвердил, что конечная точка API работает и имеет результаты. Единственные предупреждения в моем коде связаны с неиспользуемыми объявлениями.

Вот суть моего кода (немного обновленного с момента моего другого связанного поста).

App.js:

import React from "react";
//import logo from "./logo.svg";
import "./App.css";
//import SearchForm from "./searchForm";
import AssetTypes from "./controls/AssetTypes";
import { GlobalProvider } from "./context/GlobalState";
import { BrowserRouter as Router, Switch, Route } from "react-router-dom";

function App() {
  return (
    <div className="App">
      Home
      <AssetTypes></AssetTypes>
      {/* <GlobalProvider>
        <Router>
          <Switch>
            <Route exact path="/" component={Home} />
            <Route path="/assetTypes" component={AssetTypes} />
          </Switch>
        </Router>
      </GlobalProvider> */}
    </div>
  );
}

export default App;

AssetTypes.js

import React from "react";
import { NativeSelect } from "@material-ui/core";

import { useLUGet } from "../services/Http";

function AssetTypes() {
  let path = `/AssetTypes?organizationId=999`;
  console.log("path: " & path);

  console.log("before useLUGet");
  const { status, data, error } = useLUGet(path);  // ***THIS IS THE STICKING POINT***
  console.log(JSON.stringify(data));
  console.log("after useLUGet");

  return (
    <>
      <h1>Asset Types</h1>

      <NativeSelect>
        <option>stuff</option>
        {data &&
          data.map((item) => (
            <option value={item.assetTypeId}>
              {item.assetCategory} - {item.assetTypeName}
            </option>
          ))}
      </NativeSelect>
    </>
  );
}

export default AssetTypes;

Http.js

import { useEffect, useRef, useReducer } from "react";

const API_URL_BASE = "https://localhost:5001/api";

// Example usage:
// {status === 'idle' && (<div> Let's get started by searching for an article! </div>)}
// {status === 'error' && <div>{error}</div>}
// {status === 'fetching' && <div className="loading"></div>}
// {status === 'fetched' && (<>Do something with {data} object</>)

export const useLUGet = (path) => {
  console.log("in useLUGet");
  console.log("path: " & path);
  console.log("API_URL_BASE: " & API_URL_BASE);
  // const cache = useRef({});

  const url =
    API_URL_BASE &
    "/" &
    (path && path.substring(0, 1) === "/" ? path.substring(1) : path);

  console.log("url: " & url);

  const initialState = {
    status: "idle",
    error: null,
    data: [],
  };

  console.log("initial state: *** " & JSON.stringify(initialState));

  const [state, dispatch] = useReducer((state, action) => {
    switch (action.type) {
      case "FETCHING":
        return { ...initialState, status: "fetching" };
      case "FETCHED":
        return { ...initialState, status: "fetched", data: action.payload };
      case "FETCH_ERROR":
        return { ...initialState, status: "error", error: action.payload };
      default:
        return state;
    }
  }, initialState);

  useEffect(() => {
    let cancelRequest = false;
    console.log("url: " & url);
    if (!url) return;

    const fetchData = async () => {
      dispatch({ type: "FETCHING" });
      //if (cache.current[url]) {
      //  const data = cache.current[url];
      //  dispatch({ type: "FETCHED", payload: data });
      //} else {
      try {
        const response = await fetch(url);
        const data = await response.json();
        //cache.current[url] = data;
        if (cancelRequest) return;
        dispatch({ type: "FETCHED", payload: data });
      } catch (error) {
        if (cancelRequest) return;
        dispatch({ type: "FETCH_ERROR", payload: error.message });
      }
      //}
    };

    fetchData();

    return function cleanup() {
      cancelRequest = true;
    };
  }, [url, path]);

  return state;
};

Вывод консоли:

[HMR] Waiting for update signal from WDS...
AssetTypes.js:8 0
AssetTypes.js:10 before useLUGet
Http.js:12 in useLUGet
Http.js:13 0
Http.js:14 0
Http.js:22 0
Http.js:30 0
AssetTypes.js:13 []
AssetTypes.js:14 after useLUGet
AssetTypes.js:8 0
AssetTypes.js:10 before useLUGet
Http.js:12 in useLUGet
Http.js:13 0
Http.js:14 0
Http.js:22 0
Http.js:30 0
AssetTypes.js:13 []
AssetTypes.js:14 after useLUGet
Http.js:47 0

person mateoc15    schedule 08.10.2020    source источник
comment
Что заставляет вас думать, что useEffect(()=>{...}, []) противоречит правилам магического крючка? Возможно, ознакомьтесь с useEffect документами. Правила линтинга для хуков — это просто общие рекомендации, чтобы избежать устаревшего состояния.   -  person Drew Reese    schedule 09.10.2020
comment
В приведенном выше коде я получаю ошибку компиляции, в частности эту строку в AssetTypes.js const {статус, данные, ошибка} = useLUGet (путь) Ошибка: ./src/controls/AssetTypes.js Строка 14:37: React Hook useLUGet нельзя вызывать внутри обратного вызова. React Hooks должен вызываться в функциональном компоненте React или пользовательской функции React Hook react-hooks/rules-of-hooks Можно ли как-то обойти ошибку? А если так, то я не уверен, что чувствую себя комфортно с этим - переубедите меня! :) Я весь во внимании.   -  person mateoc15    schedule 09.10.2020
comment
Использование хука useLUGet кажется правильным, я не вижу проблем и работает в этом файле codesandbox, однако я вижу, что вы выполняете какие-то странные побитовые операции И (&). Похоже, вы хотели использовать + для конкатенации строк, но вместо этого использовали амперсанд &. Кажется вероятным, что вы создали неверный URL-адрес, и выборка не удалась, что вызвало некоторую проблему с условным вызовом. Можете ли вы попробовать воспроизвести свою проблему в рабочих кодах и дать ссылку здесь?   -  person Drew Reese    schedule 09.10.2020