Home > Software engineering >  React Query Hook Not Running On Initial Load
React Query Hook Not Running On Initial Load

Time:02-05

Here is my React component. The hook I am trying to get to work is useGetNotesQuery. On initial load of the component, it does not run. If I tab switch, or create a new note, then the hook will be called and the component will update. I don't have this problem with other hooks and I can't seem to figure out what I am doing wrong. I'm still pretty new to react-query. I've verified that when the hook is called on tab switch or the creation of a new note, the correct data is being passed in and the hook works as expected. It just will not run on initial load.

import React, { useState } from 'react';
import useGetNotesQuery from 'hooks/notes/useNotes';

import { useCreateNote } from 'hooks/notes/useCreateNote';

import Note from './Note';

export default function Notes({ projectItemId, itemId, itemType }: any) {
  const createNote = useCreateNote();

  const {
    data: notes,
    isLoading,
    isError
  } = useGetNotesQuery({ projectItemId, itemId, itemType });
  const [body, setBody] = useState('');

  const createNewNote = async () => {
    await createNote.mutateAsync({
      body,
      projectItemId,
      itemId,
      itemType
    });

    setBody('');
  };

  return (
    <section aria-labelledby="notes-title">
      {!isLoading && (
        <div className="sm:overflow-hidden sm:rounded-lg">
          {console.log(notes)}
          <div className="divide-y divide-gray-200">
            <div className="px-4 py-5 sm:px-6">
              <h2
                id="notes-title"
                className="text-lg font-medium text-gray-900"
              >
                Notes
              </h2>
            </div>
            <div className="px-4 py-6 sm:px-6">
              <ul role="list" className="space-y-8">
                {notes?.map((note) => (
                  <Note key={note.id} note={note} />
                ))}
              </ul>
            </div>
          </div>
          <div className="bg-gray-50 px-4 py-6 sm:px-6">
            <div className="flex space-x-3">
              {/* <div className="flex-shrink-0">
                <img
                  className="h-10 w-10 rounded-full"
                  src={user.imageUrl}
                  alt=""
                />
              </div> */}
              <div className="min-w-0 flex-1">
                <form action="#">
                  <div>
                    <label htmlFor="comment" className="sr-only">
                      About
                    </label>
                    <textarea
                      id="comment"
                      name="comment"
                      rows={3}
                      className="block w-full p-2 rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500 sm:text-sm text-black"
                      placeholder="Add a note"
                      value={body}
                      onChange={(e) => setBody(e.target.value)}
                    />
                  </div>
                  <div className="mt-3">
                    <button
                      type="submit"
                      onClick={(e) => {
                        e.preventDefault();
                        createNewNote();
                      }}
                      className="inline-flex items-center justify-center rounded-md border border-transparent bg-blue-600 px-4 py-2 text-sm font-medium text-white shadow-sm hover:bg-blue-700 focus:outline-none focus:ring-2 focus:ring-blue-500 focus:ring-offset-2"
                    >
                      Comment
                    </button>
                  </div>
                </form>
              </div>
            </div>
          </div>
        </div>
      )}
    </section>
  );
}

Here is the hook

import { getNotesById } from './../../queries/notes/get-notes';
import { useQuery } from 'react-query';

function useGetNotesQuery({ projectItemId, itemId, itemType }: any) {
  return useQuery('notes', async () => {
    if (projectItemId) {
      return getNotesById({ projectItemId, itemId, itemType }).then(
        (result) => result.data
      );
    }
  });
}

export default useGetNotesQuery;

My _app.tsx file in NextJS

import 'styles/main.css';
import 'styles/chrome-bug.css';
import '@/styles/tailwind.css';
import 'katex/dist/katex.css';
import '../styles/globals.css';
import 'react-datepicker/dist/react-datepicker.css';

import { useEffect, useState } from 'react';
import React from 'react';
import { SessionContextProvider } from '@supabase/auth-helpers-react';
import { createBrowserSupabaseClient } from '@supabase/auth-helpers-nextjs';
import { AppProps } from 'next/app';
import { MyUserContextProvider } from 'utils/useUser';
import type { Database } from 'types_db';
import { SidebarProvider } from 'context/SidebarContext';
import { QueryClient, QueryClientProvider } from 'react-query';
// import { ReactQueryDevtools } from 'react-query/devtools';
import { ThemeProvider } from 'next-themes';

const queryClient = new QueryClient({
  defaultOptions: {
    queries: {
      retry: 3
    }
  }
});

export default function MyApp({ Component, pageProps }: AppProps) {
  const [initialContext, setInitialContext] = useState();
  const [supabaseClient] = useState(() =>
    createBrowserSupabaseClient<Database>()
  );
  useEffect(() => {
    document.body.classList?.remove('loading');
  }, []);

  return (
    <QueryClientProvider client={queryClient}>
      <SessionContextProvider supabaseClient={supabaseClient}>
        <MyUserContextProvider initial={initialContext}>
          <SidebarProvider>
            <ThemeProvider
              attribute="class"
              enableColorScheme={false}
              defaultTheme="light"
            >
              <Component {...pageProps} />
            </ThemeProvider>
            {/* <ReactQueryDevtools initialIsOpen={false} /> */}
          </SidebarProvider>
        </MyUserContextProvider>
      </SessionContextProvider>
    </QueryClientProvider>
  );
}

CodePudding user response:

It is possible that the issue is that the hook is being called before the SessionContextProvider has finished setting up and the data needed for the query is not yet available. Try wrapping the useGetNotesQuery call in an useEffect hook and set the SessionContextProvider as the dependency. This will ensure that the hook is called after the SessionContextProvider is finished setting up.

CodePudding user response:

What do your other hooke return? Your query getNotesById is returning result.data, but the useQuery structure expects a parsed result object, like the example below:

const fetchUsers = async () => {
  const res = await fetch("https://jsonplaceholder.typicode.com/users");
  return res.json();
};

const response = useQuery("users", fetchUsers);
  • Related