realm / realm-js

Realm is a mobile database: an alternative to SQLite & key-value stores
https://realm.io
Apache License 2.0
5.62k stars 558 forks source link

RJS-2673: Prevent flickering behavior in `RealmProvider` #6550

Closed elle-j closed 1 month ago

elle-j commented 2 months ago

What, How & Why?

This PR makes the internal fields of User non-enumerable in order to hide them during deep comparisons. It also updates the UserProvider to only setUser() when specific fields change.

A plausible reason for the flickering behavior described in #6333 is:

  1. The user in UserProvider would continuously have its listener added (and removed) (in v0.6.2), setting the user to a new reference in its listener callback each time.
  2. ..causing RealmProvider to rerender whenever the user is a new reference.
  3. ..causing RealmProvider to check if the configuration has changed (!areConfigurationsIdentical()) and force a rerender if it has. In cases where it should not have changed, the function indicated that it had. The function uses Lodash's isEqual() which does a deep comparison that included the User's internal fields as they were still enumerable. For objects with properties being set to functions (e.g. User.listeners.options), those will be different references if the user itself is a different reference.
  4. ...causing the useEffect callback where the Realm is opened and closed in RealmProvider to run (setting the realm to the opened realm, then to null when unmounted). The switch between realm and null renders either the children or the fallback respectively. The repeated behavior causes the flickering.

This closes #6333

☑️ ToDos