Почему не axios получает токен только после перезагрузки страницы?
Когда прохожу авторизацию jwt токен записывается в localstorage. Но в запросах токен не летит, после перезагрузки страницы всё нормально
Хук useAuth для авторизации:
import { useState, useCallback, useEffect } from 'react'
const storageName = 'test'
export const useAuth = () => {
const [token, setToken] = useState(null)
const [ready, setReady] = useState(false)
const [userId, setUserId] = useState(null)
const login = useCallback((jwtToken, id) => {
setToken(jwtToken)
setUserId(id)
window.localStorage.setItem(storageName, JSON.stringify({
userId: id, token: jwtToken
}))
}, [])
const logout = useCallback(() => {
setToken(null)
setUserId(null)
window.localStorage.removeItem(storageName)
}, [])
useEffect(() => {
const data = JSON.parse(window.localStorage.getItem(storageName))
if (data && data.token) {
login(data.token, data.userId)
}
setReady(true)
}, [login])
return { login, logout, token, userId: userId, ready }
}
import axios from 'axios'
const development = process.env.NODE_ENV !== 'production'
const getToken = () => {
let token = null
const localStorage = window.localStorage.getItem('test')
if (localStorage) token = JSON.parse(localStorage).token
return token
}
export default axios.create({
baseURL: development ? 'http://localhost:5005' : 'https://test.com',
headers: { authorization: `Bearer ${getToken()}` }
})
Функция подтверждение авторизации:
const onSubmitAuth = useCallback(async values => {
await axios.post(`/api/auth`, values)
.then(res => {
login(res.data.token, res.data.id)
history.push('/hero/city')
})
.catch(err => {
setError(err)
})
}, [])
Ответы (2 шт):
import axios from 'axios'
const development = process.env.NODE_ENV !== 'production'
const getToken = () => {
let token = null
const localStorage = window.localStorage.getItem('test')
if (localStorage) token = JSON.parse(localStorage).token
return token
}
const instance = axios.create({
baseURL: development ? 'http://localhost:5005' : 'https://test.com'
})
instance.interceptors.request.use((config) => {
config.headers.Authorization = `Bearer ${getToken()}`
return config
})
export default instance
Можно просто обновлять значение заголовка в дефолтных настройках экземпляра axios (созданного при экспорте модуля).
Либо в login, если не смущает импорт экземпляра axios в том же модуле:
const login = useCallback((jwtToken, id) => {
setToken(jwtToken)
setUserId(id)
window.localStorage.setItem(storageName, JSON.stringify({
userId: id, token: jwtToken
}))
axios.defaults.headers.authorization = `Bearer ${jwtToken}`
}, [])
, либо в onSubmitAuth (здесь это более логично, по-моему):
const onSubmitAuth = useCallback(async values => {
await axios.post(`/api/auth`, values)
.then(res => {
login(res.data.token, res.data.id)
axios.defaults.headers.authorization = `Bearer ${res.data.token}`
history.push('/hero/city')
})
.catch(err => {
setError(err)
})
}, [])
Разница с вариантом принятого ответа - в том, что эти два варианта не потребуют никакого усложнения перехватчиком запросов (который вызывается при каждом запросе, и при каждом запросе он будут через функцию getToken дергать localStorage, бесполезно перечитывая и репарся одно и то же значение).
Мы добавляем токен в общую конфигурацию при его получении, и все.