Make sure no intermediate states leak from UserProvider
This is a fix for two bugs in UserProvider
.
Bug 1: setUser(await getUserInfo())
The first bug was simply that setUser
was being passed the output of getUserInfo
which always returns undefined
. Although there was an effect being used to setUser
properly, some race condition could let this undefined
value be the last value set. This bug has been in the code for a long time but just now appeared after some extra renders were eliminated.
Bug 2: The UserProvider
context was leaking intermediate user states. In order to be logged in we need both the userInfo
and the userRoles
data. However, these are currently separate API queries and it was possible for UserProvider
to be in a state where only one of these was defined. This happened any time one query returned while the other was still processing. In bug #1, userRoles
was defined but userInfo
(through the bug) was set to undefined
. This is not really a valid state for the user context, but it was still passed down to all context subscribers.
The fix is to create a new hook useUser
which combines these two API calls and returns a single user
state which is always valid. Then, UserProvider
can use a new state value
which is updated only when everything is in a valid state.
One benefit of this is reduced renders of the Application tree. During login, the previous version of UserProvider
caused around 6 rerenders of all child components (almost the whole App tree). Now, there are only 3: (initial load, not logged in, logged in)