If you’ve logged into the app recently, you might have noticed a peculiar detail: no matter who you were, the application insisted you were the same person. The header displayed a static, hardcoded string for development purposes.
While this was fine for early testing, it was time for the UI to recognize you.
Today, we are rolling out a comprehensive update to our identity management system. We have replaced the hardcoded placeholders with dynamic data injection and implemented a real-time sync engine to keep your profile consistent across the app.
Here is the technical breakdown of how we achieved "Zero-Latency" identity.
Part 1: The "Zero-Latency" Load
The naive solution to displaying a user's name is to fire a GET /api/me request immediately after login. However, that introduces network latency and a "pop-in" effect where the header loads empty, then snaps to the text seconds later.
Instead, we utilized data we already possess: the JWT (JSON Web Token).
When you log in, the backend sets a connections_token cookie. This token contains a payload with your name and email. By decoding this client-side, we get immediate access to your identity without a network trip.
The Implementation
We modified App.tsx to include a decryption hook. When the app detects a logged-in state, it reads the cookie and uses the browser’s native atob() function to decode the payload.
TypeScript
// App.tsx Logic
useEffect(() => {
if (isLoggedIn) {
const token = getCookie('connections_token');
const payload = JSON.parse(atob(token.split('.')[1])); // Decode payload
setUserName(payload.name);
setUserEmail(payload.email);
}
}, [isLoggedIn]);
These values are then passed down to the <Header /> component as props, instantly replacing the hardcoded values with your actual name.
Part 2: The Synchronization Problem
Reading from the token solved the initial load, but it created a new problem: Staleness.
The JWT is immutable for the duration of your session. If you navigated to Settings and updated your name, the database would update successfully, but the Header would still stubbornly display the old name stored in the cookie. You would have to refresh the page to see your changes.
To fix this, we implemented the profile-update-sync pattern.
The Fix: Circular Data Flow
We needed a way for a deep child component (ProfileSettings) to communicate with the root parent (App). We achieved this by passing an onUserUpdated callback down the component tree.
- App.tsx: Defines a handler that updates the
userNameanduserEmailstate. - ProfileSettings.tsx: Accepts this handler as a prop.
- The Trigger: When the "Save Changes" API call returns a
200 OK, we trigger the callback with the new data.
// ProfileSettings.tsx
const handleSave = async () => {
const response = await fetch(`${API_BASE_URL}/updateUser`, { ... });
if (response.ok) {
// Immediate UI reflection
onUserUpdated?.(fullName, email);
}
};The Result
The data flow is now complete. When you update your profile, the change is reflected instantly in the header without a page reload.
Note: This update affects the in-memory UI state only. Your JWT cookie will still contain your old name until the next time you log out and log back in, but the user experience remains seamless and accurate for the duration of the session.