Empresas
Empregos
  • Sobre nós
  • Soluções
    • Publicação de vagas
      Publique sua vaga e receba candidatos qualificados em 48h.
    • Avaliações de candidatos
      Mais de 500 testes técnicos e psicológicos, mais anti-fraude.
    • Headhunting
      Busca executiva personalizada do início ao fim.
    • Folha de Pagamento + EOR
      Dispersão de folha e EOR em mais de 15 países da LATAM.
  • Preços
  • Empregos

0

379
Visualizações
access token from auth0provider outside of react components

I'm using the auth0 token provided by the user on login to make api calls via useAuth0.getTokenSilently.

In this example, fetchTodoList, addTodoItem, and updateTodoItem all require a token for authorization. I'd like to be able to extract these functions out in to a separate file (like utils/api-client.js and import them without having to explicitly pass in the token.

import React, { useContext } from 'react'
import { Link, useParams } from 'react-router-dom'
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
import { faCircle, faList } from '@fortawesome/free-solid-svg-icons'
import axios from 'axios'
import { queryCache, useMutation, useQuery } from 'react-query'
import { TodoItem } from '../models/TodoItem'
import { TodoInput } from './TodoInput'
import { TodoList as TodoListComponent } from './TodoList'
import { TodoListsContext } from '../store/todolists'
import { TodoListName } from './TodoListName'
import { TodoList } from '../models/TodoList'
import { useAuth0 } from '../utils/react-auth0-wrapper'

export const EditTodoList = () => {

  const { getTokenSilently } = useAuth0()

  const fetchTodoList = async (todoListId: number): Promise<TodoList> => {
    try {
      const token = await getTokenSilently!()

      const { data } = await axios.get(
        `/api/TodoLists/${todoListId}`,
        {
          headers: {
            Authorization: `Bearer ${token}`
          }
        }
      )
      return data
    } catch (error) {
      return error
    }
  }

  const addTodoItem = async (todoItem: TodoItem): Promise<TodoItem> => {
    try {
      const token = await getTokenSilently!()

      const { data } = await axios.post(
        '/api/TodoItems',
        todoItem,
        {
          headers: {
            Authorization: `Bearer ${token}`,
          }
        }
      )
      return data
    } catch (addTodoListError) {
      return addTodoListError
    }
  }

  const updateTodoItem = async (todoItem: TodoItem) => {
    try {
      const token = await getTokenSilently!()

      const { data } = await axios.put(
        '/api/TodoItems',
        todoItem,
        {
          headers: {
            Authorization: `Bearer ${token}`,
          }
        }
      )
      return data
    } catch (addTodoListError) {
      return addTodoListError
    }
  }

  const [updateTodoItemMutation] = useMutation(updateTodoItem, {
    onSuccess: () => {
      queryCache.refetchQueries(['todoList', todoListId])
    }
  })

  const [addTodoItemMutation] = useMutation(addTodoItem, {
    onSuccess: () => {
      console.log('success')
      queryCache.refetchQueries(['todoList', todoListId])
    }
  })

  const onAddTodoItem = async (todoItem: TodoItem) => {
    try {
      await addTodoItemMutation({ 
        ...todoItem, 
        todoListId: parseInt(todoListId, 10) 
      })
    } catch (error) {
      // Uh oh, something went wrong
    }
  }

  const { todoListId } = useParams()
  const { status, data: todoList, error } = useQuery(['todoList', todoListId], () => fetchTodoList(todoListId))
  const { todoLists, setTodoList } = useContext(TodoListsContext)
  const todoListIndex = todoLists.findIndex(
    list => todoListId === list.id.toString()
  )

  const setTodoItems = (todoItems: TodoItem[]) => {
    // if(todoList) {
    //   const list = { ...todoList, todoItems }
    //   setTodoList(todoListIndex, list)
    // }
  }

  const setTodoListName = (name: string) => {
    // setTodoList(todoListIndex, { ...todoList, name })
  }

  return (
    <>
      <Link className="block flex align-items-center mt-8" to="/">
        <span className="fa-layers fa-fw fa-3x block m-auto group">
          <FontAwesomeIcon 
            icon={faCircle} 
            className="text-teal-500 transition-all duration-200 ease-in-out group-hover:text-teal-600" 
          />
          <FontAwesomeIcon icon={faList} inverse transform="shrink-8" />
        </span>
      </Link>

      {status === 'success' && !!todoList && (
        <>
          <TodoListName
            todoListName={todoList.name}
            setTodoListName={setTodoListName}
          />
          <TodoInput 
            onAddTodoItem={onAddTodoItem} 
          />

          <TodoListComponent
            todoItems={todoList.todoItems}
            setTodoItems={setTodoItems}
            updateTodo={updateTodoItemMutation}
          />
        </>
      )}
    </>
  )
}

Here's a link to the repo: https://github.com/gpspake/todo-client

over 4 years ago · Santiago Trujillo
4 Respostas
Responde à pergunta

0

There are different ways to solve this.

To not change your code base too much. I would go with a store with a provider and a hook. There are many store libraries out there.

Here is a tiny version which also can be used outside React rendering.
https://github.com/storeon/storeon

This was just one example of a very small store I could find that might fit the bill.

Using a store library outside React could look like:

import store from './path/to/my/store.js;'

// Read data
const state = store.get();

// Save data in the store
store.dispatch('foo/bar', myToken);
over 4 years ago · Santiago Trujillo Relatório

0

I'm not exactly sure why you couldn't access the token inside of your individual functions? Is it because they wouldn't be React function components but just regular functions?

One of the things I have done is create a useFetch hook that can get the user token and attach it to a request itself. Then, instead of exporting those functions specifically,I can just call this new fetch hook. Here's an example of what I mean.

import React from "react"
import { useAuth0 } from "../utils/auth"

const useFetch = () => {
  const [response, setResponse] = React.useState(null)
  const [error, setError] = React.useState(null)
  const [isLoading, setIsLoading] = React.useState(false)
  const { getTokenSilently } = useAuth0()

  const fetchData = async (url, method, body, authenticated, options = {}) => {
    setIsLoading(true)
    try {
      if (authenticated) {
        const token = await getTokenSilently()
        if (!options.headers) {
          options.headers = {}
        }
        options.headers["Authorization"] = `Bearer ${token}`
      }
      options.method = method
      if (method !== "GET") {
        options.body = JSON.stringify(body)
      }
      const res = await fetch(url, options)
      const json = await res.json()
      setResponse(json)
      setIsLoading(false)
      if (res.status === 200) {
        return json
      }
      throw { msg: json.msg }
    } catch (error) {
      console.error(error)
      setError(error)
      throw error
    }
  }
  return { response, error, isLoading, fetchData }
}

export default useFetch
over 4 years ago · Santiago Trujillo Relatório

0

This is a variant of the answer by @james-quick, where I am using a "RequestFactory" to generate requests in the axios format, and then just adding the auth header from Auth0

I was facing the same issue, and I got around this limitation by moving all my API call logic into a custom hook that I created:

import { useAuth0 } from '@auth0/auth0-react';
import { useCallback } from 'react';
import makeRequest from './axios';

export const useRequest = () => {
  const { getAccessTokenSilently } = useAuth0();

  // memoized the function, as otherwise if the hook is used inside a useEffect, it will lead to an infinite loop
  const memoizedFn = useCallback(
    async (request) => {
      const accessToken = await getAccessTokenSilently({ audience: AUDIANCE })
      return makeRequest({
        ...request,
        headers: {
          ...request.headers,
          // Add the Authorization header to the existing headers
          Authorization: `Bearer ${accessToken}`,
        },
      });
    },
    [isAuthenticated, getAccessTokenSilently]
  );
  return {
    requestMaker: memoizedFn,
  };
};

export default useRequest;

Usage Example:

 import { RequestFactory } from 'api/requestFactory';

 const MyAwesomeComponent = () => {
   const { requestMaker } = useRequest(); // Custom Hook
   ...
   requestMaker(QueueRequestFactory.create(queueName))
     .then((response) => {
       // Handle response here
       ...
     });
 }

RequestFactory defines and generates the request payload for my different API calls, for example:

export const create = (queueName) => ({ method: 'post', url: '/queue', data: { queueName } });

Here is a full Auth0 integration PR for reference.

over 4 years ago · Santiago Trujillo Relatório

0

I was having a similar issue on how to use getAccessTokenSilently outside of a React component, what I ended up with was this:

My HTTP client wrapper

export class HttpClient {
  constructor() {
    HttpClient.instance = axios.create({ baseURL: process.env.API_BASE_URL });

    HttpClient.instance.interceptors.request.use(
      async config => {
        const token = await this.getToken();

        return {
          ...config,
          headers: { ...config.headers, Authorization: `Bearer ${token}` },
        };
      },
      error => {
        Promise.reject(error);
      },
    );

    return this;
  }

  setTokenGenerator(tokenGenerator) {
    this.tokenGenerator = tokenGenerator;
    return this;
  }

  getToken() {
    return this.tokenGenerator();
  }
}


On my App root, I pass the getAccessTokenSilently from auth0

 useEffect(() => {
    httpClient.setTokenGenerator(getAccessTokenSilently);
  }, [getAccessTokenSilently]);

And that's it!

You now have an axios instance ready to do authenticated requests with

over 4 years ago · Santiago Trujillo Relatório
Responde à pergunta
Encontrar trabalhos remotos

Descubra a nova forma de encontrar um emprego!

melhores empregos
Principais categorias de trabalho
Empresas
Postar vaga Preços Comercial
Jurídico
Termos e Condições Política de privacidade
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomende algumas ofertas para mim
Preciso de ajuda