Skip to content

Commit

Permalink
[realm/react] Use the same function reference for the listener when t…
Browse files Browse the repository at this point in the history
…riggering rerender.
  • Loading branch information
elle-j committed Apr 5, 2024
1 parent b1106a1 commit 7c85fe7
Showing 1 changed file with 35 additions and 27 deletions.
62 changes: 35 additions & 27 deletions packages/realm-react/src/UserProvider.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
//
////////////////////////////////////////////////////////////////////////////

import React, { createContext, useContext, useEffect, useState } from "react";
import React, { createContext, useContext, useEffect, useReducer, useState } from "react";
import type Realm from "realm";

import { useApp } from "./AppProvider";
Expand All @@ -35,44 +35,52 @@ type UserProviderProps = {
children: React.ReactNode;
};

function userWasUpdated(userA: Realm.User | null, userB: Realm.User | null) {
if (!userA && !userB) {
return false;
} else if (userA && userB) {
return (
userA.id !== userB.id ||
userA.state !== userB.state ||
userA.accessToken !== userB.accessToken ||
userA.refreshToken !== userB.refreshToken
);
} else {
return true;
}
}

/**
* React component providing a Realm user on the context for the sync hooks
* to use. A `UserProvider` is required for an app to use the hooks.
*/
export const UserProvider: React.FC<UserProviderProps> = ({ fallback: Fallback, children }) => {
const app = useApp();
const [user, setUser] = useState<Realm.User | null>(() => app.currentUser);
const [, forceUpdate] = useReducer((x) => x + 1, 0);

// Support for a possible change in configuration
if (app.currentUser?.id != user?.id) {
setUser(app.currentUser);
const currentUser = app.currentUser;
if (userWasUpdated(user, currentUser)) {
setUser(currentUser);
}

useEffect(() => {
const event = () => {
let userHasChanged = false;
const currentUser = app.currentUser;
if (currentUser && user) {
userHasChanged =
currentUser.id !== user.id ||
currentUser.state !== user.state ||
currentUser.accessToken !== user.accessToken ||
currentUser.refreshToken !== currentUser.refreshToken;
} else if (currentUser || user) {
userHasChanged = true;
}

if (userHasChanged) {
setUser(app.currentUser);
}
};
user?.addListener(event);
app?.addListener(event);
return () => {
user?.removeListener(event);
app?.removeListener(event);
};
}, [user, app]);
app.addListener(forceUpdate);

return () => app.removeListener(forceUpdate);
}, [app]);

useEffect(() => {
user?.addListener(forceUpdate);

return () => user?.removeListener(forceUpdate);

/*
eslint-disable-next-line react-hooks/exhaustive-deps
-- We should depend on `user.id` rather than `user` as the ID will indicate a new user in this case.
*/
}, [user?.id]);

if (!user) {
if (typeof Fallback === "function") {
Expand Down

0 comments on commit 7c85fe7

Please sign in to comment.