function useRequest() { const [accessToken, setAccessToken] = useState(42); const [refreshToken, setRefreshToken] = useState(7); const request = async (url) => { try { const res = await axios.get(url, { Headers: { Auth: accessToken } }); } catch (error) { if (error.response.status === 401) { refresh(() => request(url)); } } } const refresh = async (callback) => { const res = await axios.get("myserver.com", { params: { refreshToken }}); setAccessToken(res.data.accessToken); callback() } return request; }Así que quiero llamar a esta API y actualizar el token de acceso si caduca. El problema es que cuando configuro el estado del token de acceso en la función de actualización, la devolución de llamada se llama con el estado anterior porque setState es asíncrono. En otros contextos, podría usar useEffect pero no estoy seguro de qué hacer en este caso.
Creo que desea almacenar accessToken en una ref en lugar de en un state .
Documentación oficial de reacción: https://reactjs.org/docs/hooks-reference.html#useref
useState es asíncrono porque React asume que el estado está relacionado con la interfaz de usuario, por lo que las actualizaciones de estado están acopladas al ciclo de vida de procesamiento de React.
La actualización de la ref es síncrona y es una buena opción para conservar datos que no necesitan activar actualizaciones de la interfaz de usuario.
Tu código, pero usando useRef
function useRequest() { const accessTokenRef = useRef(42); const [refreshToken, setRefreshToken] = useState(7); const request = async (url) => { try { const res = await axios.get(url, { Headers: { Auth: accessTokenRef.current } }); } catch (error) { if (error.response.status === 401) { refresh(() => request(url)); } } } const refresh = async (callback) => { const res = await axios.get("myserver.com", { params: { refreshToken }}); accessTokenRef.current = res.data.accessToken; callback() } return request; }Si no desea utilizar useEffect por cualquier motivo, otra opción sería pasar el estado que estableció a la función de request , para que no dependa de variables externas.
const request = async (url, accessToken = 42) => { try { const res = await axios.get(url, { Headers: { Auth: accessToken } }); } catch (error) { if (error.response.status === 401) { refresh((accessToken) => request(url, accessToken)); } } } const refresh = async (callback) => { const res = await axios.get("myserver.com"); const { accessToken } = res.data; setAccessToken(accessToken); callback(accessToken); }