反应高阶函数返回钩子

时间:2020-05-07 05:03:18

标签: javascript reactjs typescript react-hooks eslint

当前,我有一个用javascript编写的自定义提取数据挂钩,并且可以正常工作

import {useState, useEffect} from 'react';

const useApi = apiName => id => {
  const [response, setResponse] = useState();
  const [loading, setLoading] = useState(true);
  const [error, setError] = useState(false);
  const fetching = async () => {
    setLoading(true);
    const data = await fetch(`/api/${apiName}${id ? `/${id}` : ""}`)
      .then((x) => x.json())
      .catch((error) => setError(error));

    setResponse(data);
    setLoading(false);
  };

  useEffect(() => {
    fetching();
  }, [id]);

  return { response, loading, error };
};

然后,我可以在要调用的api中使用pass来获取钩子。例如:

const useCustomer = useApi("customer")
const useHello = useApi("hello")
.....
const {response, loading, error} = useCustomer("id_1")

它工作正常。

然后,我尝试转换为打字稿

const useApi = (apiName:string) => (id?:string) => {
  const [response, setResponse] = useState({})
.......
}

eslint抱怨

React Hook "useState" cannot be called inside a callback. React Hooks must be called in a React function component or a custom React Hook function

我想知道这种方法有什么问题,我知道我可以做些类似的事情:

const useApi = (apiName:string, id?:string) => {} 

或禁用附加功能(react-hooks / rules-of-hooks)

但是只是好奇具有钩子的高阶函数的潜在问题是什么,因为它实际上返回了响应。

谢谢

2 个答案:

答案 0 :(得分:0)

当您命名时,您可以使用prefix钩子进行操作,根据常规,eslint会将其视为自定义钩子。现在,在嵌套函数中实现useState,这就是为什么它会给您带来错误的原因

编写上述代码的最好方法是不使用currying函数,而是直接将apiName作为参数传递

const useApi = (apiName, id) => {
  const [response, setResponse] = useState();
  const [loading, setLoading] = useState(true);
  const [error, setError] = useState(false);
  const fetching = async () => {
    setLoading(true);
    const data = await fetch(`/api/${apiName}${id ? `/${id}` : ""}`)
      .then((x) => x.json())
      .catch((error) => setError(error));

    setResponse(data);
    setLoading(false);
  };

  useEffect(() => {
    fetching();
  }, [id]);

  return { response, loading, error };
};

并像使用它

.....

const {response, loading, error} = useApi("customer","id_1");

P.S。挂钩是HOC的替代品,如果将挂钩本身用作HOC,则写挂钩是没有意义的

答案 1 :(得分:0)

如果您不需要将 id 变量放在钩子中,则有一种更简单的方法。您收到警告的原因是因为您的钩子位于您的 CB 中,而不是您的根函数中。

正确示例:

const useApi = (apiName:string) => {
  const [response, setResponse] = useState({});

  return (id?: string) => {
    .......
  };
}