Socket
Socket
Sign inDemoInstall

@closeio/use-abortable-effect

Package Overview
Dependencies
8
Maintainers
5
Versions
1
Alerts
File Explorer

Advanced tools

Install Socket

Detect and block malicious and high-risk dependencies

Install

    @closeio/use-abortable-effect

Super simple React hook for running abortable effects


Version published
Weekly downloads
1.1K
decreased by-10.35%
Maintainers
5
Install size
25.7 kB
Created
Weekly downloads
 

Readme

Source

use-abortable-effect

NPM JavaScript Style Guide

Super simple React hook for running abortable effects based on the AbortController API.

Check the live DEMO.

Interested in working on projects like this? Close is looking for great engineers to join our team!

Install

yarn add @closeio/use-abortable-effect

Benefits

  • Extremely lightweight (less than 500B minzipped).
  • It uses the AbortController API and it is compatible with the fetch API.
  • If a browser does not support the AbortController API then the hook behaves exactly like a regular useEffect hook. See Can I Use for browser support overview.
  • No other 3rd-party dependencies.

API differences over useEffect

  • API is compatible with useEffect, where the effect function you pass-in accepts an AbortSignal instance as a param and you can return a cleanup function that accepts an AbortController instance.
  • Supports abortable fetch requests.
  • Supports running custom operations/computations that can be easily aborted.
  • Auto-aborts effects on re-run (or component unmount), unless you provide a custom cleanup function.
useEffect(() => {
  // do something

  return () => {
    /* cleanup */
  };
}, [deps]);

const abortControllerRef = useAbortableEffect(
  (abortSignal) => {
    // do something

    return (abortController) => {
      /* do cleanup, you should probably abort */
    };
  },
  [deps],
);

Usage

Abortable fetch requests

import React from 'react';
import useAbortableEffect from '@closeio/use-abortable-effect';

export default function MyAbortableFetchComponent() {
  const abortControllerRef = useAbortableEffect((abortSignal) =>
    fetch(url, { signal: abortSignal })
      .then(/* … */)
      .catch((rejection) => {
        if (rejection.name !== 'AbortError') {
          // Re-throw or handle non-abort rejection in another way.
          return Promise.reject(rejection);
        }
      }),
  );

  const handleManualAbort = () => abortControllerRef.current.abort();

  // …
}

Arbitrary computation that can be aborted

import React from 'react';
import useAbortableEffect from '@closeio/use-abortable-effect';

export default function MyAbortableComputationComponent() {
  const abortControllerRef = useAbortableEffect(abortSignal => {
    new Promise((resolve, reject) => {
      // Should be a DOMException per spec.
      const abortRejection = new DOMException(
        'Calculation aborted by the user',
        'AbortError',
      );

      // Handle when abort was requested before starting the computation.
      if (abortSignal.aborted) {
        return reject(abortRejection);
      }

      // This simulates an expensive computation.
      const timeout = setTimeout(() => resolve(1), 5000);

      // Listen for abort request.
      abortSignal.addEventListener('abort', () => {
        clearTimeout(timeout);
        reject(abortRejection);
      });
    })
      .then(/* … */)
      .catch(rejection => {
        if (rejection.name !== 'AbortError') {
          // Re-throw or handle non-abort rejection in another way.
          return Promise.reject(rejection);
        }
      }),
  });

  const handleManualAbort = () => abortControllerRef.current.abort();

  // …
}

Custom cleanup function

import React from 'react';
import useAbortableEffect from '@closeio/use-abortable-effect';

export default function MyCustomCleanupComponent() {
  const [gotAborted, setGotAborted] = useState(false);

  const abortControllerRef = useAbortableEffect((abortSignal) => {
    fetch(url, { signal: abortSignal })
      .then(/* … */)
      .catch((rejection) => {
        if (rejection.name !== 'AbortError') {
          // Re-throw or handle non-abort rejection in another way.
          return Promise.reject(rejection);
        }
      });

    // Just return a function like in `useEffect`, with the difference that you
    // get the abort controller (not a ref) as a param.
    return (controller) => {
      controller.abort();
      setGotAborted(true);
    };
  });

  const handleManualAbort = () => abortControllerRef.current.abort();

  // …
}

License

MIT © Close

FAQs

Last updated on 18 Jun 2020

Did you know?

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Install

Related posts

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc