Netlify Identity causing unexplained layout bugs in React components

Netlify Identity appears to be interacting with my Gatsby site in puzzling ways. Setup: the site is comprised of many React components that show different content based on whether the user is logged in.

The issue: several React components that depend on user data are being rendered with crazy and unexplained layouts, with borked CSS and HTML.

This only happens in the following conditions:

  • Only affects components that return different content based on netlifyIdentity.currentUser()
  • Only while logged in, i.e. logged out states are rendered correctly
  • Only happens on production (ugh…)
  • Only happens on initial page load: if the user navigates to a new page and come back to the original page, all components are rendered correctly

This is 100% replicable under the conditions above. Here’s what I believe is happening:

  • page loads with netlifyIdentity.currentUser() == null, React components are rendered in logged out state
  • Netlify Identity takes a few seconds to authenticate the user in the background
  • netlifyIdentity.currentUser() now has a value, React components aren’t rerendered and left in an in-between state

I’m honestly not sure what’s happening. Is there a way to trigger a component rerender when Netlify Identity has updated the value of netlifyIdentity.currentUser()?

Hi @DavidChouinard,

This is more of a React and your code question than a Netlify question. If your changing your UI based on values that change after initial render, then you need to account for the different data that you can get back, or the lack of that data. You didn’t provide details on what’s wrong, meaning, is the issue that your page renders incorrectly because an email isn’t available? I don’t know. But the answer in either case is, how are you accounting for this data being there vs not being there? it’s not specific to Identity since you should be doing this with any data you’re getting that can be variable.

Also if you want your components to rerender when you get the results of the currentUser(), then you should probably just be putting it in your apps component or global state. When your state changes it will cause your components to rerender, unless you have made specific code changes to prevent that rerendering. Like passing memoizing with react.memo, or one of several lifecycle methods available in class based components.

This is a question of react and just being familiar with React design patterns more so than Identity, since Identity doesn’t control how your React Components render, it’s the code you write in those components that determine how they render.

You didn’t provide details on what’s wrong, meaning, is the issue that your page renders incorrectly because an email isn’t available?

Some components render differently for logged in users (some components are behind a paywall — for paid users the content is shown, for logged out users a paywall is shown).

The issue is that components get rendered in a weird half-state between logged in and logged out, having parts of HTML/CSS from each. I hypothesize this is due to netlifyIdentity.currentUser() having changed without forcing a re-render.

if you want your components to rerender when you get the results of the currentUser() , then you should probably just be putting it in your apps component or global state .

I’m not sure I follow. You would have this.state = {currentUser: netlifyIdentity.currentUser()} in the constructor of the top-level component?

How would React know that netlifyIdentity.currentUser() has been updated?

If there was an event that Netlify Identity threw when the value was set, we could certainly trigger a re-render of the component (unfortunately, Netlify Identity doesn’t expose that — the login event is only triggered when a user manually logs in, not when a returning user is automatically logged in after a few seconds on the page).

Sorry if I’m not sufficiently familiar with React, I’m just not sure how to get React to rerender if Netlify Identity doesn’t expose an event that something has changed.

David,

Thanks for the response. What you probably want to do is have a componentDidMount or useEffect life cycle method that runs netlifyIdentity.gotrue.currentUser().jwt().then(jwt => console.log(jwt)) and in the .then function you save the user data you need to state. There are other details that depend on the structure of your app. I assume since you’re using this data in multiple places you have a global state store that you would put it in and then have it accessed further down the component tree.

In your components that depend on that data you can use a spinner or some kind of loading indicator that changes to content based on the result of that currentUser state.

1 Like

I just tried that and netlifyIdentity.gotrue.currentUser() is null (by definition!) so the rest of the expression (...jwt().then(jwt => console.log(jwt))) doesn’t work.

Is there another way to detect when currentUser() moves from null to having a value? I’m sure it’d be possible to poll netlifyIdentity.currentUser(), but that seems very clunky.

Hi,

You won’t have a currentUser until after the netlify identity widget is initialized. Are you running netlifyIdentity.init() as per the docs?