#useQuery and useEffect

4 messages · Page 1 of 1 (latest)

minor garnet
#

i'm using local global state with zustand to minimise the amount of queries i make . the issue im having is that i have a custom hook which calls a convex query and sets app state. the app local state is set within a useffect and re-runs every time the payload (result) from the backend changes, but it looks like the useeffect if re-ran on set time interval regardless of the payload changes, so it acts like there is an infinite loop.

export function useMagicRatioData({  }: { } = {}) {
  const isUserSignedIn = isAuthenticated && isSignedIn ;
  //? queries
  const { data: result,isError: isErrorMagicRatioData } = useQueryWithStatus(api.insightsMagicRatio.getCurrentMagicRatioQuery,
    isUserSignedIn
      ? {
      }
      : "skip"
  );
  //? mutations
  const mutationCurrentMagicRatioNew = useMutation(api.insightsMagicRatio.getCurrentMagicRatioMutation);
  //? state management
  const setMagicRatioData = useUserConfigStore(state => state.setMagicRatioData);
  useEffect(() => {
    console.log("🔄 useMagicRatioData",);

    if (useMutate) return;
    if (!isAuthenticated || !isSignedIn || isConvexLoading || !isClerkLoaded) return;

    //? uses data from backend when a new event has been created or deleted
    if (result?.success && result?.payload?.personalAllData.combined
      && result?.payload?.partnerAllData.combined
      && !testMode) {
      const newData = {
 some data...
      };
      if (newData.personalAllData && newData.partnerAllData && newData.zones) {
        setMagicRatioData({
          zones: newData.zones,
          personalAllData: newData.personalAllData,
          partnerAllData: newData.partnerAllData,
          lastUpdated: newData.lastUpdated,
          isErrorMagicRatio: false,
          isPendingMagicRatio: false
        });
    }
  },[result?.payload?.partnerAllData,result?.payload?.personalAllData]);

@fluid raft

fluid raftBOT
#

Hi @minor garnet. I'm kapa.ai, your friendly support bot. I will try to answer your question by searching through the knowledge base. :wave:

#

Based on the code snippet and description you've provided, it seems you're experiencing an issue with your custom hook useMagicRatioData. The problem appears to be related to how useEffect and useQuery are interacting. Let's break down the issue and suggest a solution:

  1. The useEffect dependency array includes result?.payload?.partnerAllData and result?.payload?.personalAllData. This means the effect will run every time these values change.

  2. useQuery (or in your case, useQueryWithStatus) is reactive by default. It will update the result whenever the underlying data in the Convex backend changes, even if the change doesn't affect the actual data you're using.

To address this issue, you have a few options:

  1. Use useStableQuery: This is a custom hook provided by Convex that can help reduce unnecessary re-renders. It's designed to skip intermediate undefined states and only update when new data is available. You can find more information about this in the Help, my app is overreacting! (https://stack.convex.dev/help-my-app-is-overreacting#impacting-how-the-querys-reacting) article.

  2. Implement your own caching mechanism: You could use the ConvexQueryCacheProvider as described in the Magic Caching (https://stack.convex.dev/magic-caching) article. This can help reduce unnecessary re-fetches and re-renders.

  3. Use useMemo to memoize the data you're setting in your state:

#
const memoizedData = useMemo(() => {
  if (result?.success && result?.payload?.personalAllData.combined
    && result?.payload?.partnerAllData.combined
    && !testMode) {
    return {
      zones: newData.zones,
      personalAllData: newData.personalAllData,
      partnerAllData: newData.partnerAllData,
      lastUpdated: newData.lastUpdated,
      isErrorMagicRatio: false,
      isPendingMagicRatio: false
    };
  }
  return null;
}, [result]);

useEffect(() => {
  if (memoizedData) {
    setMagicRatioData(memoizedData);
  }
}, [memoizedData, setMagicRatioData]);

This approach will ensure that the effect only runs when the actual data you care about changes, not on every update from the Convex backend.

  1. Consider using useStableQuery as mentioned in the Convex React documentation (https://docs.convex.dev/client/react#fetching-data). This custom hook can help manage the reactivity of your queries more effectively.

Remember, the goal is to reduce unnecessary re-renders and updates while still maintaining reactivity where it's needed. You might need to experiment with these approaches to find the one that works best for your specific use case.

Note: you can ask me a follow up question by @ mentioning me again :speech_balloon: