Possible to trigger ApiProvider update when ApiClient header value becomes available?
Closed this issue · 2 comments
Thank you for this awesome package! After user login, I add a userToken to localStorage for use in all requests via ApiClient headers
. Since this value is initially undefined, when localStorage updates, it does not trigger the update to ApiProvider
's client
. Is there a good strategy to get ApiProvider
to re-render with the updated client
value?
const client = new ApiClient({
url: 'http://localhost:5000/api/v1',
schema,
headers: {
'Authorization': `Bearer ${localStorage.getItem('userToken')}`
}
});
const Root = () => {
return (
<ApiProvider client={client}>
<App />
</ApiProvider>
);
};
ReactDOM.render(<Root />, document.querySelector("#root"));
Hi @firstgeneration ,
One approach would be to store your token in a context (or some other state management). That way, when the the context is updated, react will re-render <Root />
with the new token:
const getClient = (token) => new ApiClient({...});
const Root = () => {
const token = useContext(TokenContext)
return (
<ApiProvider client={getClient(token)}>
<App />
</ApiProvider>
);
}
<Root />
will need to be the child of a <TokenContext />
. This strategy will wipe the jsonapi-react cache, but that shouldn't be an issue when logging in/out.
Alternatively you could attach the token header by providing your own fetch:
function fetchWithToken(url, options) {
const token = localStorage.getItem('userToken')
if (token) {
if (!options)
options = {}
options.headers = {
...options.headers,
Authorization: `Bearer ${localStorage.getItem('userToken')}`
}
}
return fetch(url, options)
}
const client = new ApiClient({
url: 'http://localhost:5000/api/v1',
schema,
fetch: fetchWithToken
})
You could use this to check for 401 (or other non-2xx) responses:
async function fetchWithToken(url, options) {
// ... attach token
const result = fetch(url, options)
if (result.status === 401) {
const newToken = fetchRefreshToken(token)
// ... put new token in storage
return fetchWithToken(url, options)
}
return result
}
@jonahsol Thanks so much for the reply! Finally wrapped my head around contexts yesterday to implement a global currentUser
. Started to realize a context would be good for handling the token too. Your snippets are much appreciated!