【问题标题】:React higher order function to return hook反应高阶函数返回钩子
【发布时间】:2020-08-22 07:18:18
【问题描述】:

目前,我有一个用 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 来获取钩子。例如:

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) => {} 

或禁用 eslint(react-hooks/rules-of-hooks)

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

谢谢

【问题讨论】:

  • 我的猜测是 ESLint 规则无法识别它只是柯里化,它认为这是一个无效的钩子使用。

标签: javascript reactjs typescript react-hooks eslint


【解决方案1】:

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

正确示例:

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

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

【讨论】:

    【解决方案2】:

    当你用prefix 钩子命名你的函数时,eslint 认为它是根据一般约定的自定义钩子。现在在嵌套函数中实现了 useState 这就是它给你一个错误的原因

    上述代码最好的写法是不使用柯里化函数,而是直接将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");
    

    附: Hooks 旨在作为 HOC 的替代品,如果您将其用作 HOC 本身,那么编写 hook 是没有意义的

    【讨论】:

    • 为什么不只是 // eslint-disable-next-line react-hooks/rules-of-hooks,因为 OP 知道他只是在使用curruying? (这是生成自定义钩子 IMO 的有效方法)
    • @EmileBergeron 这也是一种方式。
    猜你喜欢
    • 2020-06-19
    • 2020-08-20
    • 1970-01-01
    • 2022-11-02
    • 2021-11-11
    • 1970-01-01
    • 2021-08-28
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多