Quickly Accessing User Preferences
Hopefully you find this reading helpful! I thought to write it as I was working on a new feature.
Intro
When we're working on a feature that is reliant on user preferences, it's usually best not to make an API call to figure out user preferences every time. '
The code snippets below are all generalized, but they're based off a real scenario for Bluebird Documentation (BBD).
Enhanced Right Click Scenario
The Problem
I'm adding an "enhanced right click", so when a user right clicks, they're shown a custom menu; with some of the options specifically chosen by them. Take a look at the image below.
This is the "enhanced right click" in action. The user right clicks, and they're brought up with this menu; instead of the usual menu users are brought up with when right clicking. As you might notice, some of the options are normal like full screen mode and refresh, but the rest are different. The middle options are for quick navigation to certain features, but the top two options are actually set by the user. If the user frequently references a particular space, page, etc in BBD, they can set those links in the account settings page. At the same time though, I don't want to force this feature on all users.
This is a situation where we don't want to query the backend every time the user right clicks, but we still need to keep these top two options (whether they want the enhanced right click or not) up to date if they're ever changed.
The solution
When I first was thinking of this, three ideas came to mind: session storage, local storage, and global state.
I thought that I could query the backend once (when the user logs in, updates account settings, etc), and put that user preference to have the enhanced right click feature or not in session/local storage or global state. This brings up a couple of concerns.
- Which is fastest retrieval? Don't want any delay every time a user right clicks.
- Will the preference stay across all browsers?
Now it's worth noting that a developer could make any of these options work. However, the situation does get a little trickier with session and local storage because the developer would need to be cautious to make sure that session and local storage are in sync with the user preferences. Another point is, while all three options are still very fast, the fastest is global state. When retrieving from global state, it's like accessing any variable in memory. Whereas local and session storage involve a browser API call, which is still very fast for small data that we're involving, but slightly slower than accessing global state. Also, down the road, using global state is a lot better for scalability. The more features we add, the more we would stack onto local or session storage; the speed difference between accession global state and local/session storage might become more noticeable.
In the solution, query the backend on app load/user authentication.
This component allows any other component to access to update preferences.
Now, in any other component, I can access that preference, and take action based off that value.
Of course, there are other considerations like updating global state along with the backend when a user updates their preferences, but the above snippets are simplified examples to showcase an implementation of the solution.
Outro
This is the solution that I went with, but there are definitely things I would need to consider with global state as well.
With global state, I do have to "hydrate" that value every time the web app is reloaded. It's not like session storage or local storage that would stay after a reload. However, I still found that a lot neater than having to make sure that session or local storage was up to date. It's easier because I can visually see my global state variables in my code; as opposed to local or session storage, I'd just have to keep track of what I'm setting, which is something that could get complex as more features are added.
Please share any thoughts, questions, etc in the comments below! I myself still have a lot of learning to do; I'd appreciate any feedback you have on the implementation.
Part of: LinkedIn Articles