0

I've got a very simple function set up to (eventually) load data from AsyncStorage. Currently I'm not even using AsyncStorage, but I'm just trying to make sure I'm using Promises correctly. Here is my simple code to get such a Promise:

Storage.ts:

export async function poll(key: string): Promise<any> {
  try {
    console.log("polling");
    return new Promise((resolve, reject) => {
      resolve("Promised value.");
    });
  } catch (e) {
    // TODO: Log something.
  }
}

Then I'm trying to retrieve the promise here in my functional component:

ExampleAsyncComponent.tsx:

import React, { useEffect, useState } from "react";
import { ReactElement } from "react-native/node_modules/@types/react";
import { poll } from "./Storage";
import { Text, View } from "react-native";

export default function ExampleAsyncComponent(): ReactElement {
  const [value, setValue] = useState<any>(null);
  const [refreshCount, setRefreshCount] = useState<number>(0);

  const loadedValuePromise: Promise<any> = poll("some.key");
  const updateValue = async () => {
    loadedValuePromise.then((v) => {
      setRefreshCount(refreshCount + 1);
      console.log("then count: " + refreshCount);
      setValue(v);
    });
  };

  useEffect(() => {
      setInterval(() => {
        updateValue();
      }, 2000);
  });

  return (<View><Text>hello</Text></View>);
}

I've added some logs to the console to try and visualize/debug how all of this is working, but I'm getting a LOT more logs than I would've expected. With the code above, I would've expected "polling" to be printed out once and then every couple of seconds I would see "then count: x". However, it looks like I'm starting up a bunch of promises (and in my mind, I think that means I'm starting up a bunch of threads). The longer this application runs in the browser (where I'm debugging my React Native app) the crazier the output gets, but here's the output from my app running for just a few seconds:

enter image description here

So I guess I have a couple of questions. Is this to be expected? If so, should I be expiring my promises somehow (I haven't found any examples of that yet)? If this isn't to be expected, what am I doing wrong?

Austin Brown
  • 830
  • 12
  • 24
  • You are implementing a `setInterval` function within a no-dependecy `useEffect`, which means your function will be called each 2000ms (or any other period specified in the `setInterval` implementation), considering the code, this seems to be the expected behavior. PD: See [this](https://stackoverflow.com/a/53057776/7737346) comment for relatively complete explanation of async/await compared to `.then()` – KBeDev Oct 20 '21 at 15:57
  • It seems that my function is being called more than once each 2000ms, though. It looks like it's getting called multiple times every 2000ms. – Austin Brown Oct 20 '21 at 19:22
  • 1
    Yes, that's because the called function trigger a render each time the state is updated – KBeDev Oct 20 '21 at 20:13
  • Ah, okay. Then yeah I guess I'm trying to figure out how to stop the function from triggering once I've gotten the value from the `Promise`. – Austin Brown Oct 20 '21 at 22:06

1 Answers1

1

Effects need a list of dependencies as their second param.

  // Calling poll in the render loop is surely a mistake
  // const loadedValuePromise: Promise<any> = poll("some.key");

  const updateValue = async () => {
    poll("some.key").then((v) => {
      setRefreshCount(refreshCount + 1);
      console.log("then count: " + refreshCount);
      setValue(v);
    });
  };

  useEffect(() => {
      setInterval(() => {
        updateValue();
      }, 2000);
  // An effect with an empty list of dependencies will run once on mount
  // and then never again.
  }, []);
windowsill
  • 3,599
  • 1
  • 9
  • 14
  • I believe this is working! I had to read up on what exactly the dependency list was, but I think this makes sense now. – Austin Brown Oct 20 '21 at 23:01