如何正确调用useFetch函数?

时间:2019-08-29 01:06:35

标签: reactjs react-hooks

我已经成功实现了useFetch函数来调用API端点。如果将这样的代码添加到这样的功能性React组件的根目录中,它会完美地发挥作用:

  const [{ data, isLoading, isError }] = useFetch(
    'http://some_api_endpoint_path'
  );
export const useFetch = (url) => {
  const [data, setData] = useState();
  const [isLoading, setIsLoading] = useState(false);
  const [isError, setIsError] = useState(false);

  useEffect(() => {
    const fetchData = async () => {
      setIsError(false);
      setIsLoading(true);
      try {
        const response = await axios.get(url);
        setData(response.data);
      } catch (error) {
        setIsError(true);
      }
      setIsLoading(false);
    };

    fetchData();
  }, [url]);
  return [{ data, isLoading, isError }];
};

但是,假设我要检查是否存在新输入的username,例如,在触发输入元素的onBlur事件时。当我尝试实施此操作时,出现此错误:

React Hook "useFetch" is called in function "handleBlur" which is neither a React function component or a custom React Hook function  react-hooks/rules-of-hooks

我什至尝试了这种方法:

  const [isChanged, setIsChanged] = useState(false);

  useEffect(() => {
    useFetch(
      'http://some_api_endpoint_path'
    );
  }, [isChanged]);

但是有同样的错误。

然后我尝试了这个简化的版本,该版本没有任何用处,但我正在测试React Hooks规则:

  useEffect(() => {
    useFetch(
      'http://some_api_endpoint_path'
    );
  }, []);

我仍然遇到相同的错误。

尤其是在最近的两个案例中,我感到我遵守了《胡克规则》,但显然没有!

在这种情况下致电useFetch的正确方法是什么?

1 个答案:

答案 0 :(得分:0)

我想你是这样打useFetch的,对吧?

const onBlur = () => {
  const [{ data, isLoading, isError }] = useFetch(
    'http://some_api_endpoint_path'
  );
  ...
}

如果为true,这是错误的。检出此link

  

?不要调用事件处理程序。

您可以通过以下方式实现:

// Pass common initial for all fetches.
export const useFetch = (awsConfig, apiRoot, apiPathDefault) => {
  const [data, setData] = useState();
  const [isLoading, setIsLoading] = useState(false);
  const [isError, setIsError] = useState(false);

  // Just pass the variables that changes in each new fetch requisition
  const fetchData = async (apiPath) => {
      setIsError(false);
      setIsLoading(true);
      try {
        const response = await axios.get(apiRoot + apiPath);
        setData(response.data);
      } catch (error) {
        setIsError(true);
      }
      setIsLoading(false);
    };

  useEffect(() => {
    fetchData(apiRoot + apiPathDefault);
  }, [awsConfig, apiRoot, apiPathDefault]);

  return [{ data, isLoading, isError }, fetchData];
};

每当您想再次获取时,只需致电fetchData

const [{ data, isLoading, isError }, fetchData] = useFetch(API_ROOT(), appStore.awsConfig, defaultPath);

const onBlur = () => {
  fetchData(newPath);
  ...
}

我使用了与创建useLazyQuey时使用的Apollo团队相同的原理(请打开此link并搜索useLazyQuery)。另外,请注意,当我调用该钩子时,我传递了所有常见且不可变的变量,而在一次访存中仅传递了可变变量。