reactjs - 调用 javascript 函数时使用 react hooks 的正确方法是什么?

标签 reactjs react-hooks

我只是在学习 Hook 如何在较大的应用程序中工作。我想弄清楚这里的正确模式是什么。我通常将我的 api 调用包装在它们自己的文件中。例如,我可能会调用以获取文件 Customers.Api.js 中的客户列表:

import axios from 'axios';

const client = await getApiClient();
const reply = await client.get(`${baseUrl}/customers`);
return reply;

getApiClient() 的工作是获取一个已经添加了 Authorization header 的 axios 实例。我是从 Auth0 那里得到的,但这部分并不重要,因为我真的在这里寻找模式而不是 Auth0 的特定模式,可能是任何钩子(Hook):

// Engine.Api.js
// Inside an axios interceptor called from getApiClient()
const { getAccessTokenSilently } = useAuth0(); // <-- this is not allowed in a plain js func

const token = await getAccessTokenSilently({}); 
request.headers.Authorization = `Bearer ${token}`;
...
return request

由于我的 token 来自钩子(Hook),我应该如何设置它?

我不想每次都这样做:

const { getAccessTokenSilently } = useAuth0();
const token = await getAccessTokenSilently({});
const client = await getApiClient();
const reply = await client.get(`${baseUrl}/customers`,{
  headers: `Authorization: Bearer ${token}`,
})

我更喜欢某种方式来做到这一点(或类似的东西):

const customers = await getCustomers();

getCustomers() 将存在于 Customers.Api.js 中,并且会有如下内容:

const client = await getApiClient(); // <-- this would use interceptor to add bearer
return await client.get(`${baseUrl}/customers`);

Final Solution

看完安德烈所说的内容后,我终于到了我需要去的地方。这是我最终做的:

const axiosClient = axios.create();

export function useApiClient() {
  const { getAccessTokenSilently, isLoading } = useAuth0();
  const [state, setState] = useState({
    loading: true,
    authHeader: null,
    token: '',
    client: null,
  });

  useEffect(() => {
    (async () => {
      if (!isLoading) {
        if (state.token === '') {
          const apiToken = await getAccessTokenSilently({
            audience: 'https://example.com/',
            scope: 'read:current_user',
          });
          setState({ ...state, authHeader: { Authorization: `Bearer ${apiToken}` }, token: apiToken });
    }

    if (state.token && !state.client && state.loading) {
      setState({ loading: false, client: axiosClient });
    }
  }
})();
}, [getAccessTokenSilently, state, isLoading]);
  return { ...state };

之后我也对其进行了很多修改,因为这并不是我真正的用例,但它确定了我不理解的地方。 谢谢安德烈!!!!

最佳答案

这通常通过创建另一个钩子(Hook)来解决,该钩子(Hook)将所有必要的逻辑包装在里面。

Auth0 文档实际上有一个例子:https://github.com/auth0/auth0-react/blob/master/EXAMPLES.md#4-create-a-useapi-hook-for-accessing-protected-apis-with-an-access-token

在你的情况下你可以这样做:

Customers.Api.js:

export function useCustomers() {
  const [state, setState] = useState({ customers: [] });
  const { getAccessTokenSilently } = useAuth0();
  useEffect(() => {
    (async () => {
      const token = await getAccessTokenSilently({});
      const client = await getApiClient();
      const reply = await client.get(`${baseUrl}/customers`,{
        headers: `Authorization: Bearer ${token}`,
      })
      setState({ customers: reply.data });
    })
  });
  return state;
}

(未经测试,可能无法实际工作,但希望思路清晰)

在组件中:

const { customers } = useCustomers();

下一步是将 useCustomers Hook 概括为 useApi 之类的东西,并在 useCustomers 内部简单地调用 useApi

您还可以找到官方 Building Your Own Hook文档很有帮助,它解释了最常见的问题。

关于reactjs - 调用 javascript 函数时使用 react hooks 的正确方法是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/65499465/

相关文章:

javascript - 如何打开新页面并滚动到 id 而不影响 URL?

javascript - 递减 setState 中的计数器

reactjs - jsPDF , TypeError : pdf. fromHTML 不是 REACT 中的函数

reactjs - 如何在React中一键重置多个计数器

javascript - 已经设置后,如何将 React Hooks 设置为另一个值

javascript - 将 const 值存储在变量和状态之间有区别吗?

javascript - react useEffect 和异步获取

javascript - 我们如何、何时以及为何清理 React JavaScript 中的组件?

javascript - React + Redux Fetch Data - 干净的解决方案

reactjs - 如何在 React Router Dom 的 useHistory 中发送参数?