skip to Main Content

I’m looking to fetch pages from wikipedia API.
for the sake of keeping this short I won’t explain in deep, but the bottom line is that i need to use what returned in previous request (when resolved) as params in a new one.

    "batchcomplete": "",
    "continue": {
        "grncontinue": "0.117298963004|0.117302224597|46297018|0",
        "continue": "grncontinue||"

I’ve tried sevral appraoches, here’s my latest try:

 const results = useQueries([
    {
      queryKey: [`getRandomWikis-${count}`],
      queryFn: async () => {
        const res = await axios.get(url + endpoint);
        setEndpoint(`&grncontinue||=${res.data?.data?.continue?.grncontinue}`);
        setCount((prev) => prev + 1);
        setAllData((prev) => [...prev, res.data?.data?.query?.pages]);
        return res;
      },
      enabled: isLocalStorageEmpty,
    },
    {
      queryKey: [`getRandomWikis-${count}`],
      queryFn: async () => {
        const res = await axios.get(url + endpoint);
        setEndpoint(`&grncontinue||=${res.data?.data?.continue?.grncontinue}`);
        setCount((prev) => prev + 1);
        setAllData((prev) => [...prev, res.data?.data.query.pages]);
        return res;
      },
      enabled: isLocalStorageEmpty && count > 1,
    },
    {
      queryKey: [`getRandomWikis-${count}`],
      queryFn: async () => {
        const res = await axios.get(url + endpoint);
        setEndpoint(`&grncontinue||=${res.data?.data?.continue?.grncontinue}`);
        setCount((prev) => prev + 1);
        setAllData((prev) => [...prev, res.data?.data.query.pages]);
        return res;
      },
      enabled: isLocalStorageEmpty && count > 2,
    },
  ]);

  results[2].data?.data && console.log(allData);

i’m getting endless requeast for some reason, my component rerenders many times until craches, and nothing is logged to console.

Ideas? Am I using useQueries wrong? different approaches? (here I made 3 request but the idea is to be able to make even more)

2

Answers


  1. Chosen as BEST ANSWER

    I went for this solution eventualy and it works, BUT: it ignores the whole 'continue' dependency on one another. That failed miserably, but in my specific case it didn't seem to matter eventualy if you limit your requset to 20 pages per request. For other cases it probabloy is still needed so if you know how to handle that dependency do tell.

     const results = useQueries(
        Array.from({ length: pages }, (_, i) => i).map((index) => {
          return {
            queryKey: [`getRandomWikis-${index}`],
            queryFn: async () => {
              const res = await axios.get(url);
              return res;
            },
            enabled: !isStored, // only if isStored is falsy (meaning: no items in storage), run the query.
          };
        })
      );
    
      useEffect(() => {
        if (results[pages - 1].data?.data) {
          // if last query resolved,
          const allWikis = results.reduce((acc, result) => {
            // rejoin all pages
            return [...acc, ...Object.values(result.data.data.query.pages)];
          }, []);
    
          setAllData(allWikis);
          setDoneFetch(true);
        }
      }, [results[pages - 1].data?.data]);
    
      useStoreWikiData(allData); // store in local storage.
    
      return doneFetch; // returns a boolean indicting fetching is in progress (false) or has finished (true)
    

    However, I had to bypass react-query's isLodaing, IsError and other features for they were not working at all in useQueries (maybe I wasn't using them correctly, inlighten me). So I manged the states manually, not that horrible.


  2. This can be simplified quite a lot if you do the following:

    • create a custom hook for the query and implement it multiple times
    • remove setAllData() and simply refer to data returned from the hook
    // create a custom hook
    const useWiki = (grncontinue) =>
      useQuery({
        queryKey: ['getRandomWikis', grncontinue],
        queryFn:() => {
          const fullUrl = grncontinue ? url : `&grncontinue||=${grncontinue}`;
          return axios.get(fullUrl).then(({data}) => return data);
        },
        enabled: isLocalStorageEmpty
      })
            
          
    // and implement it multiple times in component
    const {data: firstData} = useWiki();
    const {data: secondData} = useWiki(firstData?.continue?.grnContinue)
    const {data: thirdData} = useWiki(secondData?.continue?.grnContinue)
    
    console.log([...firstData, ...secondData, ...thirdData]);
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search