1

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.

usersina
  • 1,063
  • 11
  • 28

1 Answers1

1

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])
Lothric
  • 1,283
  • 2
  • 6
  • 11
  • Works fluently, thank you! Quick question though: How do you recommend trying to fetch the data X times instead of indefinitely ? – usersina Mar 30 '20 at 16:24
  • 1
    @AnisBenna you can make `otherErrorFetchedChecker` be integer instead of boolean. Make it zero by default. So your if statement can be `if (data && otherErrorFetchedChecker < 5)` for example. And if request fails `setOtherErrorFetchedChecker(c => c++)` – Lothric Mar 30 '20 at 16:34