realm-js icon indicating copy to clipboard operation
realm-js copied to clipboard

Realm slows down app performance when updating multiple screen with react-navigation/native

Open shanoysinc opened this issue 1 year ago • 5 comments

Problem

here is a discussion about the problem - https://github.com/realm/realm-js/discussions/6490 Is there a solution to prevent useQuery from re-rendering a screen that you're not currently on? If so, could you please provide an example?

Solution

Whenever you trigger an update in Realm, useQuery gets updated, causing every screen in the bottom tab that uses useQuery to re-render. Is there a way to prevent this, so it only triggers a re-render when you visit that screen, and only if there was an update?

Alternatives

No response

How important is this improvement for you?

Would be a major improvement

Feature would mainly be used with

Local Database only

shanoysinc avatar Jan 10 '25 23:01 shanoysinc

Yhea we had to use enableFreeze() (https://github.com/react-navigation/react-navigation/discussions/11241)

Acetyld avatar Mar 11 '25 13:03 Acetyld

Hi @shanoysinc , Has this issue been resolved? I'm very interested in knowing if there's a solution. If you get any solution Please let me know!

Thank you!

renukaAmplework avatar Apr 28 '25 07:04 renukaAmplework

Yhea we had to use enableFreeze() (react-navigation/react-navigation#11241)

when freeze is enabled, animations stop working.

shanoysinc avatar Apr 28 '25 12:04 shanoysinc

Hi @shanoysinc , Has this issue been resolved? I'm very interested in knowing if there's a solution. If you get any solution Please let me know!

Thank you!

This was the solution I came up with. There's lots of room for improvement, but how it works is that Realm will only update the state when the screen is in focus. I only use this hook for screens that are in the bottom tab navigation.

` 



 import { useFocusEffect } from "@react-navigation/native";
    import { useCallback, useMemo, useRef, useState } from "react";
    import { Realm } from "@realm/react";
    
    export const useRealmQuery = <T extends object>(
      realm: Realm,
      objectType: string,
      filterQuery: string | null
    ) => {
      const result: any = useMemo(() => {
        if (filterQuery) {
          return realm.objects<T>(objectType).filtered(filterQuery);
        }
        return realm.objects<T>(objectType);
      }, [objectType, filterQuery]);
      const [data, setData] = useState<Realm.Results<T>>(result);
      const init = useRef(true);
      useFocusEffect(
        useCallback(() => {
          const updateState = () => {
            if (init.current) {
              init.current = false;
              return;
            }
            let newData: any;
            if (filterQuery) {
              newData = realm.objects<T>(objectType).filtered(filterQuery);
            } else {
              newData = realm.objects<T>(objectType);
            }
            setData(newData);
          };
    
          const listener = () => updateState();
          result.addListener(listener);
    
          return () => {
            result.removeListener(listener);
          };
        }, [filterQuery]) // Only re-run if these dependencies change
      );
    
      return data;
    };
    
`

usage

const realm = useRealm();

  const tasks = useRealmQuery<Task>(
    realm,
    "Task",
     `archived != true`
  );

shanoysinc avatar Apr 28 '25 13:04 shanoysinc

If anyone manages to improve the above implementation please let me know

shanoysinc avatar Apr 28 '25 13:04 shanoysinc