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

Allow usage of realm outside of react components #6273

Open
Fuzzyma opened this issue Nov 21, 2023 · 10 comments
Open

Allow usage of realm outside of react components #6273

Fuzzyma opened this issue Nov 21, 2023 · 10 comments

Comments

@Fuzzyma
Copy link

Fuzzyma commented Nov 21, 2023

Problem

When using @realm/react, it provides you with a ... Provider. And in child components you can use hooks to get access to your realm.
However, I want to be able to access the realm in other parts of the application that are decoupled from the react components.
I dont see a way how to do that since the realm created in the provider is always closed access

Solution

Allow to pass in a realm to the Provider that is used instead of the automatically created one.
This realm can then be used for functionality outside of react

Alternatives

Atm, I pass in a custom object to the realmRef prop that is filled with the realm and share that custom object to other parts of my application:

export const realmRef: { current: Realm | null } = { current: null }

// later
<RealmProvider realmRef={realmRef} />

However, this leads to problems with hot reloading and is really hacky

How important is this improvement for you?

I would like to have it but have a workaround

Feature would mainly be used with

Local Database only

// Edit:
I found this comment for realmRef in your code:

  /**
   * 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.
   */

So, it seems like I am using realmRef correctly - kinda. Because you cannot use useRef outside of react components to create a ref (i faked it). Also: Hot reloading breaks. If i have to guess its because a new realm is created on rerender and the old one is still around somehow

@Fuzzyma
Copy link
Author

Fuzzyma commented Nov 22, 2023

So I ended up copying a bunch of implementation files to still have access to hooks but use a global realm instance instead of an internal one. That works but ofc is super hacky

@kneth
Copy link
Member

kneth commented Dec 1, 2023

@Fuzzyma Thank you for the suggestion. We have a future project to refcount Realm instances, and I think it will be natural to return to your suggestion once we start on that project.

@AlecsFarias
Copy link

AlecsFarias commented Dec 12, 2023

@Fuzzyma

So I ended up copying a bunch of implementation files to still have access to hooks but use a global realm instance instead of an internal one. That works but ofc is super hacky

So, I'm on a project and started to implement realm on it as well, but not all things on the app is "offline first" and does not use realm, because of that we use a pretty based "services architecture" (just remove all service logic from components). I'm really curious about how you did manage to use like that, maybe it can enable my team to work with realms but still use it only on services layers, can you show a little on how you managed to do that ?

Also, I'am worried about the "sync" part, seeing examples like using an query for list and from nowhere it updates because of syncing, maybe calling a function that only get the response of a query doe's not carry the sync part and does not update until a forced refetch ? Have you seen something about that ?

@Fuzzyma
Copy link
Author

Fuzzyma commented Dec 13, 2023

I have a file where I create a new realm and export that one.
I copied over createUseObject to use the global realm instead.
Then I exported my own useRealm method that just return the global realm.
I also create my own useQuery and useObject

export const useRealm = getRealm;
export const useQuery = createUseQuery(getRealm);
export const useObject = createUseObject(getRealm);

In the react world i make sure to only import from my file and never from react realm.
All updates still work and its updating my views as expected. Its not really a suprise since I just replaced the realm (which is recreated whenever react rerenders) with a stable one

@kscgl
Copy link

kscgl commented Dec 22, 2023

@Fuzzyma Can you please share how you create a new realm?

I am new on this and trying to achieve a similar thing. I need to use the db outside of react components so I need to replace the below.

const realmConfig: Realm.Configuration = {
  schema: [Test],
  schemaVersion: 1,
};

export const {RealmProvider, useRealm, useObject, useQuery} =
  createRealmContext(realmConfig);

@Fuzzyma
Copy link
Author

Fuzzyma commented Dec 22, 2023

@kscgl I am actually experimenting again with just using useEffect in a component to save the useRealm into an outside var.

const realm = useRealm()
useEffect(() => {
  globalRealm = realm 
  // or some global func:
  setGlobalRealm(realm)
}, [realm])

When I tested this in the past, it crashed on me since realm objects were in use that were invalid but for that case you have to convert them to plain objects (I think that was the issue. still investigating)

However, that makes it exceptionally harder to use syncing because for syncing you need users and those are supplied via the user context and now you have to hack a few more files. I dont wanna do that so I try to go with the above solution.

As for what I did: I tried to explain it before. It involved copying the source code for useRealm and createUseObject and use my own realm instead of creating one there.

A realm can be created by just calling new Realm(config)

@kscgl
Copy link

kscgl commented Dec 22, 2023

@Fuzzyma I see. thanks for the explanation. I wasn't sure if you were talking about new Realm() or something else. It seems like I have to go with new Realm() and creating Services to be used everywhere and lose 'hooks' priviliges.

@takameyer
Copy link
Contributor

@Fuzzyma
Just wanted to provide some information if you are trying to use realm outside of RealmProvider.

First off, if you invoke Realm.open() with the same configuration you have passed into RealmProvider, then you will receive a shared instance of realm. Although be careful, if one of these shared instances are closed with realm.close(), then all of them will close.

Second, there is a property on RealmProvider called closeOnUnmount. Set this to false to ensure that your shared instance of realm is not closed when the RealmProvider is closed (if that's important to you).

That should provide enough flexibility to do whatever it is you need. Let me know if that helps!

@susonthapa
Copy link

@takameyer What if I call new Realm(configuration) first to create the realm instance and pass the same configuration to the createRealmContext(configuration), will I receive the same shared instance within the components that use the provider from createRealmContext?

@nikhil2882
Copy link

you can create new realm instance by using realm create with same config you used to create realmprovider
realm js

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

7 participants