Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add flag to keep Realm open on RealmProvider unmount #6088

Merged
merged 4 commits into from
Aug 23, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 3 additions & 7 deletions packages/realm-react/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,21 +4,17 @@
* None

### Enhancements
* None
* Add flag to keep realm open on unmount of `RealmProvider`. ([#6023](https://github.com/realm/realm-js/issues/6023))

### Fixed
* <How to hit and notice issue? what was the impact?> ([#????](https://github.com/realm/realm-js/issues/????), since v?.?.?)
* None

### Compatibility
* React Native >= v0.71.4
* Realm Studio v14.0.0.
* File format: generates Realms with format v23 (reads and upgrades file format v5 or later for non-synced Realm, upgrades file format v10 or later for synced Realms).
* Realm >= 11.0.0

### Internal
<!-- * Either mention core version or upgrade -->
<!-- * Using Realm Core vX.Y.Z -->
<!-- * Upgraded Realm Core from vX.Y.Z to vA.B.C -->
* Added more documentation to provider params.

## 0.5.2 (2023-08-09)

Expand Down
13 changes: 13 additions & 0 deletions packages/realm-react/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -234,6 +234,19 @@ const AppWrapper = () => {
)
}
```

It may also be necessary to render multiple `RealmProvider`s of the same Realm in an app. In this case, the flag `closeOnUnmount` can be set to `false`` to prevent both Realm instances from closing when one has been removed from the component tree.
This is set to `true` by default.

```tsx
const AppWrapper = () => {
return (
<RealmProvider closeOnUnmount={false}>
<App/>
<RealmProvider>
)
}
```
### Dynamically Updating a Realm Configuration

It is possible to update the realm configuration by setting props on the `RealmProvider`. The `RealmProvider` takes props for all possible realm configuration properties.
Expand Down
6 changes: 5 additions & 1 deletion packages/realm-react/src/AppProvider.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -52,8 +52,12 @@ const AuthOperationProvider: React.FC<AuthOperationProps> = ({ children }) => {
* https://www.mongodb.com/docs/realm-sdks/js/latest/Realm.App.html#~AppConfiguration
*/
type AppProviderProps = Realm.AppConfiguration & {
children: React.ReactNode;
/**
* A ref to the App instance. This is useful if you need to access the App
* instance outside of a component that uses the App hooks.
*/
appRef?: React.MutableRefObject<Realm.App | null>;
children: React.ReactNode;
};

/**
Expand Down
20 changes: 17 additions & 3 deletions packages/realm-react/src/RealmProvider.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,19 @@ type PartialRealmConfiguration = Omit<Partial<Realm.Configuration>, "sync"> & {
};

type ProviderProps = PartialRealmConfiguration & {
/**
* The fallback component to render if the Realm is not opened.
*/
fallback?: React.ComponentType<unknown> | React.ReactElement | null | undefined;
/**
* If false, Realm will not be closed when the component unmounts.
* @default true
*/
closeOnUnmount?: boolean;
/**
* A ref to the Realm instance. This is useful if you need to access the Realm
* instance outside of a component that uses the Realm hooks.
*/
realmRef?: React.MutableRefObject<Realm | null>;
children: React.ReactNode;
};
Expand Down Expand Up @@ -65,7 +77,7 @@ export function createRealmProvider(
* For example, to override the `path` config value, use a prop named `path`,
* e.g. `path="newPath.realm"`
*/
return ({ children, fallback: Fallback, realmRef, ...restProps }) => {
return ({ children, fallback: Fallback, closeOnUnmount = true, realmRef, ...restProps }) => {
const [realm, setRealm] = useState<Realm | null>(() =>
realmConfig.sync === undefined && restProps.sync === undefined
? new Realm(mergeRealmConfiguration(realmConfig, restProps))
Expand Down Expand Up @@ -129,11 +141,13 @@ export function createRealmProvider(

return () => {
if (realm) {
realm.close();
if (closeOnUnmount) {
realm.close();
}
setRealm(null);
}
};
}, [configVersion, realm, setRealm]);
}, [configVersion, realm, setRealm, closeOnUnmount]);

if (!realm) {
if (typeof Fallback === "function") {
Expand Down
5 changes: 4 additions & 1 deletion packages/realm-react/src/UserProvider.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,10 @@ import { useApp } from "./AppProvider";
export const UserContext = createContext<Realm.User | null>(null);

type UserProviderProps = {
// Optional fallback component to render when unauthenticated
/**
* The fallback component to render if there is no authorized user. This can be used
* to render a login screen or another component which will log the user in.
*/
fallback?: React.ComponentType<unknown> | React.ReactElement | null | undefined;
children: React.ReactNode;
};
Expand Down
12 changes: 12 additions & 0 deletions packages/realm-react/src/__tests__/RealmProvider.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,18 @@ describe("RealmProvider", () => {
expect(realm.isClosed).toBe(true);
});

it("returns the configured realm with useRealm and stays open if flagged", async () => {
const wrapper = ({ children }: { children: React.ReactNode }) => (
<RealmProvider closeOnUnmount={false}>{children}</RealmProvider>
);
const { result, unmount } = renderHook(() => useRealm(), { wrapper });
await waitFor(() => expect(result.current).not.toBe(null));
const realm = result.current;
expect(realm.schema[0].name).toBe("dog");
unmount();
expect(realm.isClosed).toBe(false);
});

it("will override the the configuration provided in createRealmContext", async () => {
const wrapper = ({ children }: { children: React.ReactNode }) => (
<RealmProvider schema={[catSchema]}>{children}</RealmProvider>
Expand Down
Loading