简体   繁体   English

如何包装在 useEffect 中使用钩子的 function?

[英]How to wrap a function that uses hooks inside a useEffect?

I wrote a function to make an API call.我写了一个 function 来进行 API 调用。 Typically, I'd just wrap it in a useEffect and throw it in the same file that needs it, but I'm trying to write my code a little cleaner.通常,我只是将它包装在一个 useEffect 中并将其放入需要它的同一个文件中,但我正在尝试将我的代码编写得更简洁一些。 So I did the following.所以我做了以下。

In my component.js file, I have the following:在我的component.js文件中,我有以下内容:

import { apiCall } from '../../../framework/api.js';
import { useEffect, useState } from 'react';

export const Table = () => {
    const [ resp, setResp ] = useState();

    
    useEffect(() => {
        console.log(apiCall());
    }, []);
    
    return(
        <>
            { resp &&
                resp.map(([key, value]) => {
                    console.log("key: " + key);
                    return(
                        <SomeComponent />
                    );
                })
            }
        </>
    );
}

in my api.js file, I have the following:在我的api.js文件中,我有以下内容:

import axios from 'axios';
import { useState } from 'react';

export const apiCall = () => {
    const [ resp, setResp ] = useState();

    axios.get('https://some.domain/api/get').then((response) => {
        setResp(response.data);
    });

    if(resp) return resp;
}

This always returns an error ( Invalid hook call. Hook calls can only be called inside the body of a function component. )这总是返回一个错误(无效的钩子调用。钩子调用只能在 function 组件的主体内调用。

If I rewrite my component.js and include the axios call directly inside useEffect instead of calling the function apiCall() from the external file, it obviously works with no problems.如果我重写我的component.js并直接在 useEffect 中包含 axios 调用,而不是从外部文件调用 function apiCall() ,它显然可以正常工作。

I think I know it has to do with the fact that I'm using hooks in my apiCall function, and wrapping that call in a useEffect in my component.js .我知道这与我在我的apiCall function 中使用钩子并将该调用包装在我的component.js中的 useEffect 中这一事实有关。 However, if I don't wrap it in a useEffect, it'll just run continuously and I don't want that either.但是,如果我不将它包装在 useEffect 中,它只会连续运行,我也不希望这样。

You have to follow the custom hook naming convention for this to be able to work.您必须遵循自定义挂钩命名约定才能使其正常工作。 You can check out the documentation for that here: https://reactjs.org/docs/hooks-custom.html您可以在此处查看相关文档: https://reactjs.org/docs/hooks-custom.html

Anyway, I believe in this case this should work:无论如何,我相信在这种情况下这应该有效:

import axios from 'axios';
import { useState } from 'react';

export const useApiCall = () => {
    const [ resp, setResp ] = useState();

    axios.get('https://some.domain/api/get').then((response) => {
        setResp(response.data);
    });

    if(resp) return resp;
}

And then in component.js , you would call useApiCall()然后在component.js中,你会调用useApiCall()

Usually, we do it like this通常,我们这样做

export const useApiCall = () => {
    const [ resp, setResp ] = useState();

    useEffect(() => {
        axios.get('https://some.domain/api/get').then((response) => {
            setResp(response.data);
        });
    }, []);

    return resp;
}

and then use it like so然后像这样使用它

export const Table = () => {
    const resp = useApiCall();
    
    return(
        <>
            { resp &&
                resp.map(([key, value]) => {
                    console.log("key: " + key);
                    return(
                        <SomeComponent />
                    );
                })
            }
        </>
    );
}

The prefix "use" in the function name is important, this is how we define a custom hook. function 名称中的前缀“use”很重要,这就是我们定义自定义钩子的方式。

React Hook "useState" is called in function "apiCall" that is neither a React function component nor a custom React Hook function. React Hook "useState" 在 function "apiCall" 中调用,它既不是React function 组件也不是自定义React Hook ZC1C425268E68385D1AB5074C17A94F1。 React component names must start with an uppercase letter. React 组件名称必须以大写字母开头。 React Hook names must start with the word "use" . React Hook 名称必须以"use"开头。

You can use following methods.您可以使用以下方法。

import { useState } from 'react';

export const ApiCall = () => {
  const [state, setState] = useState();
};

or或者

import { useState } from 'react';

export const useApiCall = () => {
  const [state, setState] = useState();
};

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM