1

i use react-query to fetch some data ,and i need to call fetchPagesContent function in useQuery after fetchlangs function is done, because i need dynamic ID of lang to use it in fetchPagesContent function how i can dow that with react-query

import React, { createContext,useState,useEffect } from 'react'
import { useQuery } from 'react-query'
        
const fetchPagesContent = async () => {
  const resp = await fetch('http://127.0.0.1:8000/api/content-pages/lang_id=1');
  return resp.json();
}
    
const fetchlangs = async () => {
  const resp = await fetch('http://127.0.0.1:8000/api/languages');
  return resp.json();
}
          
export const AppContext = createContext();
        
export default function AppContextProvider({children}) {
  const resp = useQuery('langs',fetchlangs );
  const resp = useQuery('page',fetchPagesContent);
  
  return (
    <AppContext.Provider value={resp}>
      {children}
    </AppContext.Provider>
  )
}
1
  • Something else: There shouldn't be the need to pass data from react-query down the component tree via Context. I mean you can, but the idea is more to call useQuery with the same key (best abstracted in a custom hook) wherever you need your data Commented May 12, 2021 at 10:50

3 Answers 3

4

you are looking for dependent queries, where you disable the second query via the enabled option for as long as you have no data for the first query:

const langs = useQuery('langs',fetchlangs );
const resp = useQuery('page',fetchPagesContent, { enabled: Boolean(langs.data) });
Sign up to request clarification or add additional context in comments.

Comments

0

Just as an alternative solution, you can use third-party useAsyncEffect hook to make requests or any other async things inside your component with cancelable async effects (Live Demo):

import React from "react";
import { useAsyncEffect } from "use-async-effect2";
import cpFetch from "cp-fetch/lib/native";
/*
 Note: the related network request will also be aborted
 Check out your network console
 */

function* fetchAPI(url) {
  const response = yield cpFetch(url);
  // you can use a native fetch directly, but cpFetch wrapper will abort
  // the request automatically when the async effect canceling
  return yield response.json();
}

function TestComponent(props) {
  const [cancel, done, result, err] = useAsyncEffect(
    function* () {
      this.timeout(props.timeout);
      // we use mocky-delay=2s to slowdown the response for demo purpose
      const data = yield* fetchAPI(
        "https://run.mocky.io/v3/39486170-1983-457b-a89f-b0736ccf7961?mocky-delay=2s"
      );
      return yield* fetchAPI(
        `https://rickandmortyapi.com/api/character/${data.fetchId}`
      );
    },
    { states: true }
  );

  return (
    <div className="component">
      <div className="caption">useAsyncEffect demo:</div>
      <div>
        {done
          ? err
            ? err.toString()
            : JSON.stringify(result, null, 2)
          : "loading..."}
      </div>
      <button className="btn btn-warning" onClick={cancel} disabled={done}>
        Cancel async effect
      </button>
    </div>
  );
}

Comments

0

To fetch data with useQuery after previous queries have completed in React Query, you can use the enabled option along with the onSuccess or onSettled callbacks. This allows you to conditionally trigger the subsequent query only after the previous one has completed successfully.

import { useQuery } from 'react-query';

const fetchData1 = async () => {
  // Fetch data for the first query
  const response = await fetch('/api/data1');
  return response.json();
};

const fetchData2 = async () => {
  // Fetch data for the second query
  const response = await fetch('/api/data2');
  return response.json();
};

function MyComponent() {
  const { data: data1, isLoading: isLoading1, isError: isError1 } = useQuery('data1', fetchData1);

  const { data: data2, isLoading: isLoading2, isError: isError2 } = useQuery(
    'data2',
    fetchData2,
    {
      enabled: !!data1, // This ensures fetchData2 is only called after data1 is available
    }
  );

  if (isLoading1 || isLoading2) {
    return <div>Loading...</div>;
  }

  if (isError1 || isError2) {
    return <div>Error occurred</div>;
  }

  return (
    <div>
      <h1>Data 1: {JSON.stringify(data1)}</h1>
      <h1>Data 2: {JSON.stringify(data2)}</h1>
    </div>
  );
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.