usersina
usersina

Reputation: 1845

Re-calling an async function in useEffect inside of another async function after a failed api fetching request

This is a bit tricky to explain, but here is what I'm doing:

  1. Trying to get json data from an async function called getJsonData() until data is fetched.
  2. After getting the data correctly, I want to get another set of json data from getOtherJsonData()

The following code gets me the first set of data (getJsonData) correctly even after X failures. (if any)

It doens't however get the second set of data (getOtherJsonData) all the time as an error could occur. I want to keep re-execution the bloc of code marked below until the second set of data is returned correctly.

...
import React, {useState, useEffect} from 'react';
import {getJsonData} from './getJsonData';
imoport {getOtherJsonData} from './getOtherJsonData';

const myApp = () => {
    const [errorFetchedChecker, setErrorFetchedChecker] = useState(false);
    const [isLoading,setIsLoading] = useState(true);
    const [data,setData] = useState(null);

    const updateState = jsonData => {
      setIsloading(false);
      setData(jsonData);
    };

    useEffect(() => {
      getJsonData().then(
        data => {
          updateState(data);

          // This is the bloc I want to keep re-executing
          //
          getOtherJsonData(data.title).then(
            otherData => {
              updateOtherState(otherData);
              console.log("Updated with no error);
            },
            otherError => {
            console.log("Error, try getOtherJsonData again ?");
            console.log("Can't try to refresh, no errorFetchedChecker for me :/ ");
            }
          //
          // Until It doesn't return an error

        },
        error => {
          console.log('Error fetching, re-trying to fetch thanks to errorFetchedChecker');
          setErrorFetchedChecker(c => !c);
        },
      );
    }, [errorFetchedChecker]);

    return (
      <View>
        <Text>{state.data.title}</Text>
        <Text>{data.data.completed}</Text>
      </View>
    );
}

Here's getJsonData() and getOtherJsonData()

export async function getJsonData() {
  try {
    let response = await fetch('https://jsonplaceholder.typicode.com/todos/1');
    let responseJson = await response.json();
    return responseJson;
  } catch (error) {
    throw error;
    // Should I just throw the error here ?
  }
}

export async function getOtherJsonData(oldData) {
  try {
    let response = await fetch(`https://someOtherApilink/${oldData}`);
    let responseJson = await response.json();
    return responseJson;
  } catch (error) {
    throw error;
    // Should I just throw the error here also ?
  }
}

This is my other question which explains how to re-execute the first getJsonData() in case of failure.

Below is something I tried but gave me error about unhandled promises:

const subFunction(myTitle) => {
  getOtherJsonData(myTitle).then(
    otherData => {
      updateOtherState(otherData);
      console.log("Updated with no error);
    },
    otherError => {
      console.log("Error, try getOtherJsonData again!");
      subFunction(myTitle);  //Gives Unhandled promise warning and no result
    }
}

useEffect(() => {
  getJsonData().then(
    data => {
      updateState(data);

      // This is the bloc I want to keep re-executing
      //
      subFunction(data.title);
      //
      // Until It doesn't return an error

    },
    error => {
      console.log('Error fetching, re-trying to fetch thanks to errorFetchedChecker');
      setErrorFetchedChecker(c => !c);
    },
  );
}, [errorFetchedChecker]);

Note: Feel free to rephrase the title in any way, shape or form.

Upvotes: 1

Views: 218

Answers (1)

Lothric
Lothric

Reputation: 1318

You can try to separate these two functions with using two useEffect, because now you'll have to repeat first request in case of second fail. Something like this:

useEffect(() => {
      getJsonData().then(
        data => {
          updateState(data);
        },
        error => {
          console.log('Error fetching, re-trying to fetch thanks to errorFetchedChecker');
          setErrorFetchedChecker(c => !c);
        },
      );
    }, [errorFetchedChecker]);

useEffect(() => {
    // prevent request if there's no data
    if (data) {
        getOtherJsonData(data.title).then(
            otherData => {
              updateOtherState(otherData);
              console.log("Updated with no error);
            },
            otherError => {
            console.log("Error, try getOtherJsonData again ?");
            console.log("Can't try to refresh, no errorFetchedChecker for me :/ ");
            // you'll have to create one more state for that
            setOtherErrorFetchedChecker(c => !c);
            }
    }
}, [data, otherErrorFetchedChecker])

Upvotes: 1

Related Questions