So I'm using React with React-Router.
I have a onEnter hook which checks if the user is authenticates yes/no and executes the desired action.
export function requireAuth(nextState, replaceState) {
  if (!isAuthenticated()) {
    if (!Storage.get('token')) replaceState(null, '/login');
    return delegate().then(() => replaceState(null, nextState.location.pathname));
  }
  if (nextState.location.pathname !== nextState.location.pathname) {
    return replaceState(null, nextState.location.pathname);
  }
}
When the token is expired I call a delegate function which looks like:
export function delegate() {
  const refreshToken = Storage.getJSON('token', 'refresh_token');
  return getData(endpoint)
      .then(res => {
        Storage.set('token', JSON.stringify({
          access_token: res.data.access_token,
          refresh_token: refreshToken,
        }));
      });
}
The delegate function indeed refresh the tokens in the localStorage. But the requests after the replaceState are not using the updated token, but the previous one. I think this is a async issue, someone knows more about this?
Edit: The function where I use the token:
function callApi(method, endpoint, data) {
  return new Promise((resolve, reject) => {
    let headers = {
      'Accept': 'application/json',
      'X-API-Token': Storage.getJSON('token', 'access_token'),
    };
    const body = stringifyIfNeeded(data);
    const options = { method, headers, body };
    return fetch(endpoint, options)
      .then(response =>
        response.json().then(json => ({ json, response }))
      ).then(({ json, response }) => {
        if (!response.ok) {
          reject({ json, response });
        }
        resolve(json);
      }).catch((error, response) => {
        reject({ error, response });
      });
  });
}
