Async function in useEffect

In ReScript with React, how do you make an effect with an async method inside? I can do it, but I need to put a ->ignore at the end of the promise chain to convert the Promise<unit> to a simple unit. Shouldn’t the React bindings for ReScript support an effect with a promise?

Here’s how it looks in my TypeScript that I’m migrating…

useEffect(() => {
  async function sequence() {
    await animation.start({ translateX: "50px" });
    await animation.start({ opacity: 0 }, { delay: 0.3 });
  sequence().catch((_) => {}); // run animation and swallow errors
}, [animation, i]);

Here’s what I have to do in ReScript. Notice the ->ignore at the end of the promise.

    React.useEffect2(() => {
      let sequence = () =>
        Framer.startAnimation(animation, ...)
        ->Promise.then(_ =>
          Framer.startAnimation(animation, ...))
      sequence()->Promise.catch(_ => Promise.resolve())->ignore
    }, (animation, message))

I think it’s a good thing that ReScript requires you to be explicit with a value you don’t use. In your scenario it’s a reminder: “You have a long-running operation here, the component might be unmounted before the process completes. Use the clean-up function to stop the animation before unmounting”

If it is OK for your animation library to target an unmounted component, well, you’re explicit about it with ignore.


You’ve answered your own question :slightly_smiling_face:

Whenever you use a promise as a side effect, then you will almost always need to use the ignore function to, well, ignore it. This is universally true in ReScript, not just when using React. It’s tied to how the promise bindings work.

I believe there was discussion once about having a forEach style promise binding that automatically returns unit, (and some userland promise libraries implement that), but IIRC the consensus was that it’s easier to just use ignore instead of adding an extra binding to the stdlib.

1 Like

You could also use the following:

There is also an open PR on rescript-promise to have a function Promise.done that will strictly ignore promise values so it’s a bit more typesafe than the general ignore function.

1 Like