npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

react-use-loading

v0.1.3

Published

React Hook for managing loading indicator state

Downloads

38

Readme

Actions Status

react-use-loading

Manage your component's loading state with one simple hook. Very useful if you're making AJAX requests, for example, and you want to display a spinner and a loading message to clue your users into what's going on.

Getting Started

react-use-loading is just a normal NPM library. You can install it with the following command:

npm install react-use-loading

Or, if you prefer Yarn:

yarn add react-use-loading

Then, you can use it in your code like so:

import { useLoading } from 'react-use-loading';

Usage

const [{ isLoading, message }, { start, stop }] = useLoading(
  initState,
  initMessage
);

Params

| Value | Type | Description | | ------------- | ------------------------ | ------------------------------ | | initState | boolean or undefined | Used to initialize isLoading | | initMessage | string or undefined | Used to initialize message |

Return Values

| Value | Type | Default | Description | | ----------- | ------------------------------- | ----------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | isLoading | boolean | false | Represents whether the component is engaged in loading or not | | message | string or undefined | undefined | Used to communicate to the user what loading the component is engaged in | | start | (newMessage?: string) => void | N/A | Used to toggle the hook into loading state. Results in a rerender whereafter isLoading is true and message is either a newly-specified message, or undefined if no message was specified. Memoized using useCallback. | | stop | () => void | N/A | Used the toggle the hook out of loading state. Results in a rerender whereafter isLoading is false and message is undefined. Memoized using useCallback. |

Examples

Using isLoading

This is the core reason that react-use-loading exists. Use this value to communicate whether the component is loading or not.

import React from 'react';
import { useLoading } from 'react-use-loading';

import Spinner from '../components/spinner';
import SomeComponent from '../components/some-component';

const MyComponent = () => {
  const [{ isLoading }] = useLoading(true);

  // Logic stuff...

  return isLoading ? <Spinner /> : <SomeComponent />;
};

Using message

The message variable is useful for communicating information to the user besides just the fact that your app is fetching information. For example, you could tell the user that you're fetching their profile information, or that you're saving their updated settings.

import React from 'react';
import { useLoading } from 'react-use-loading';

import Spinner from '../components/spinner';
import SomeComponent from '../components/some-component';

const MyComponent = () => {
  const [{ isLoading, message }] = useLoading(true, 'Getting profile info...');

  // Logic stuff...

  return isLoading ? <Spinner message={message} /> : <SomeComponent />;
};

Using start and stop

These methods are used for toggling loading state. They are useful for when you're making AJAX requests within the component, or when you start/stop any long-running task.

Calling start once

import React, { useState, useEffect } from 'react';
import ky from 'ky';
import { useLoading } from 'react-use-loading';

import Spinner from '../components/spinner';
import SomeComponent from '../components/some-component';

const MyComponent = () => {
  const [profileInfo, setProfileInfo] = useState();
  const [{ isLoading, message }, { start, stop }] = useLoading(
    true // Initialize `isLoading` as true so there's no flash of content
  );

  useEffect(() => {
    (async () => {
      try {
        start('Getting profile info...');
        const res = await ky.get(/* Profile data endpoint */);
        setProfileInfo(res);
      } catch (error) {
        console.error(error);
      } finally {
        stop();
      }
    })();
  }, [start, stop]); // You can include these methods in the dependency
  //                    array and be confident that they will not change.

  return isLoading ? <Spinner message={message} /> : <SomeComponent />;
};

Calling start multiple times

You can safely call start multiple times before you call stop if you would like to tell the user that you're interacting with multiple data soruces.

import React, { useState, useEffect } from 'react';
import ky from 'ky';
import { useLoading } from 'react-use-loading';

import Spinner from '../components/spinner';
import SomeComponent from '../components/some-component';

const MyComponent = () => {
  const [posts, setPosts] = useState();
  const [profileInfo, setProfileInfo] = useState();
  const [recommendations, setRecommentations] = useState();
  const [{ isLoading, message }, { start, stop }] = useLoading(
    true // Initialize `isLoading` as true so there's no flash of content
  );

  useEffect(() => {
    (async () => {
      try {
        start('Getting profile info...');
        const profileRes = await ky.get(/* Profile data endpoint */);
        setProfileInfo(profileRes);

        start('Getting your posts...');
        const postsRes = await ky.get(/* Posts endpoint */);
        setPosts(postsRes);

        start('Getting your recommendations...');
        const recommendationsRes = await ky.get(/* Recommendations endpoint */);
        setRecommendations(recommendationRes);
      } catch (error) {
        console.error(error);
      } finally {
        stop();
      }
    })();
  }, [start, stop]); // You can include these methods in the dependency
  //                    array and be confident that they will not change.

  return isLoading ? <Spinner message={message} /> : <SomeComponent />;
};

Handling Aborts

One thing to keep in mind when you're handling asynchronous requests in your component is that your component might be unmounted in the middle of a request. stop will attempt to update state behind the scenes, so when you abort your request make sure to prevent calling stop in the event of an AbortError.

import React, { useState, useEffect, useRef } from 'react'
import ky from 'ky'
import { useLoading } from 'react-use-loading'

import Spinner from '../components/spinner'
import SomeComponent from '../components/some-component'

const abortController = new AbortController()

const MyComponent = () => {
  const [profileInfo, setProfileInfo] = useState()
  const [{ isLoading, message }, { start, stop }] = useLoading(
    true // Initialize `isLoading` as true so there's no flash of content
  )

  useEffect(() => {
    return () => abortController.abort()
  }, [])

  useEffect(() => {
    ;(async () => {
      try {
        start('Getting profile info...')
        const profileRes = await ky.get(/* Profile data endpoint */, { signal: abortController.signal })
        setProfileInfo(profileRes)
        stop()
      } catch (error) {
        if (error.name === 'AbortError') return // Exit function if request was aborted
        console.error(error)
        stop()
      }
    })()
  }, [start, stop]) // You can include these methods in the dependency
                    // array and be confident that they will not change.

  return isLoading
    ? <Spinner message={message} />
    : <SomeComponent />
}

In the future, I would like to prevent stop from making a state update once the component has been unmounted, but I haven't figured out how to do that yet.

Contributing

Contributions are welcome. Please fork the repository and then make a pull request once you've completed your changes. Make sure to write new tests or alter existing ones to validate your changes as well.

Thanks

This project was bootstrapped with Jared Palmer's wonderful TSDX utility. The code itself is inspired by work I've completed for the Linux Foundation.