Displaying a loading modal while fetching data in another modal

36 views Asked by At

I have a modal in my app in which data is being fetched and display called <MyModal/>. Inside it I have another single modal called <InfoModal/> (nested) which will be shown on top of the previous one for two purposes: displaying a "Loading..." component while the data is being fetched or displaying a prompt with whatever error the API returned while attempting to fetch the data. Sort of a shapeshifting modal, depending on whether we're in a loading state or an error state.

Why am I choosing this approach: On iOS you can't show a modal on top of another one simultaneously unless they're nested just like that.

What is the problem with the code below:

Case A: If the API returns an error, on Android the loading prompt is shown briefly and then the error modal appears (this is the intended behaviour). On iOS, it skips the loading modal and it "shapeshifts" directly into the error displaying one.

Case B: If the API returns no error, the loading modal remains stuck and never closes (on both iOS and Android)

What am I doing wrong?

type Props = {
  isMyModalVisible: boolean // This is the visibility state of <MyModal/> controlled by a state residing in the screeen containing <MyModal/>
}

const MyModal = ({ isMyModalVisible }: Props) => {


  const [dataFetchedFromAPI, setDataFetchedFromAPI] = useState<any>(null); // This is the data that will be displayed inside <MyModal/>
  const [isInfoModalVisible, setIsInfoModalVisible] = useState(false);
  const [infoModalType, setInfoModalType] = useState<"Error" | "Loading | null">(null); // State which controls if the 2nd modal is in "Loading" shape or "Error displaying shape"
  const [infoModalMessage, setInfoModalMessage] = useState(""); // The message to be displayed in the 2nd modal (if it's in "Error" shape)

  useEffect(() => {
    // Fetching some data from API
    fetchDataFromAPI();
  }, [])

  const fetchDataFromAPI = async () => {
    // When the call starts, we're setting the state of the 2nd modal in "Loading" shape and its visibility to "true"
    setInfoModalType("Loading")
    setIsInfoModalVisible(true)

    dataFetchingMethod()
      .then((response: any) => {
        setDataFetchedFromAPI(response)
      })
      .catch(async (error) => {

        // In case we get an error, we set the visibility of 2nd modal to true, set it into "Error" shape and retain in a state variable the error message received from API
        setInfoModalType("Eroare")
        setInfoModalMessage(error.message)
        setIsInfoModalVisible(true);
      })
      .finally(() => {
        // After the API call is done, in case the 2nd modal was in "Loading" shape, close it
        if (infoModalType === "Loading") {
          setInfoModalType("")
          setIsInfoModalVisible(false)
        }
      })
  }

  return (
    <>
      <Modal
        animationType="slide"
        transparent={true}
        visible={isMyModalVisible}>

        <Modal
          animationType="slide"
          transparent={true}
          visible={isInfoModalVisible}>
          {
            infoModalType === "Loading"
              ?
              <View>
                {/*.....CODE FOR DISPLAYING LOADING MODAL....*/}
              </View>
              :
              <View>
                {/*.....CODE FOR DISPLAYING ERROR MODAL....*/}
              </View>

          }
        </Modal>
        <View>
          {/*....Code for <MyModal where the data fetched from the API is displayed/> */}
        </View>
      </Modal>
    </>
  )
}

export default MyModal
    
0

There are 0 answers