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-toastsnack

v1.4.0

Published

An unopinionated notification queue for React

Downloads

38

Readme

react-toastsnack

An unopinionated notification queue for React

Installation

Using npm:

$ npm install react-toastsnack

Using yarn:

$ yarn add react-toastsnack

Then with a module bundler like webpack, use as you would anything else:

// Using ES6 Modules
import { useToastSnack } from 'react-toastsnack';
// using CommonJS modules
const useToastSnack = require('react-toastsnack').useToastSnack;

Usage

At the top-level of your application, import the ReactToastSnackProvider module.

// AppContext.js
import React from 'react';
import { ReactToastSnackProvider } from 'react-toastsnack';

function AppContext() {
  return (
    <ReactToastSnackProvider>
      <App />
    </ReactToastSnackProvider>
  );
}

The provider provides (ahem) you with a set of parameters:

renderer

This prop is required, and is the component used to render a single notification.
react-toastsnack has no opinion on how you choose to render it.

Props provided to the renderer:

  • toastSnack _ id _ open _ offset _ And any other props passed upon creation of the notification.
  • onUpdate
  • onExited
  • onClose

For example, let's say we're using the material-ui component library.
The renderer may look something like this:

// AppContext.js
import React from 'react';
import { ReactToastSnackProvider } from "react-toastsnack";

import Snackbar from "@material-ui/core/Snackbar";

function AppContext() {
  return (
    <ReactToastSnackProvider renderer={ToastSnack}>
      <App />
    </ReactToastSnackProvider>
  )
}

const ToastSnack = React.memo(props => {
  const { onUpdate, onExited, onClose, toastSnack } = props;
  const {
    id,
    open,
    offset
    // Any other props are controlled by you.
    style,
    message,
    contentProps,
    autoHideDuration,
    ...other
  } = toastSnack;

  // If the snack height isn't the same as the default height
  // which we provided to ReactToastSnackProvider, we may want to update it
  const ref = useRef(null);
  useLayoutEffect(() => {
    const height = ref.current?.clientHeight;
    if (height && snackProps.height !== height) {
      onUpdate({ id, height });
    }
  }, [id, onUpdate, snackProps.height]);

  const handleClose = React.useCallback((event,reason) => {
    if (reason === "clickaway") return;
    onClose(id);
  }, [id, onClose]);

  const handleExited = React.useCallback((event) => {
    onExited(id);
  }, [id, onExited]);


  return (
    <RootRef rootRef={ref}>
      <Snackbar
        style={style}
        onClose={handleClose}
        onExited={handleExited}
        autoHideDuration={autoHideDuration}
        {...other}
      >
        <SnackbarContent
          message={message}
          {...contentProps}
        />
      </Snackbar>
    </RootRef>
  )
});

methods

The methods prop allows you to pass an object containing functions, which generate custom methods.
Any functions you provide here, can be accessed through the useToastSnack/withToastSnack api.

For example, I want to implement a notification centered around a promise.

// AppContext.js
import React from 'react';
import { ReactToastSnackProvider } from "react-toastsnack";

function AppContext() {
  const methods = React.useMemo(() => {
    // onCreate and onUpdate is passed, so we can create a custom flow.
    promise: (onCreate, onUpdate) => {
      return ({promise, ...other}) => {

        // Create a new notification and save the id to a variable
        // We've set the duration to null, in order to persist
        // the notification until the promise is resolved or rejected
        const id = onCreate({
          ...other,
          duration: null,
          color: "colorLoading",
          message: "Please wait for something",
        });

        promise
          // If the promise is resolved,
          // change the color to `colorSuccess`, update the message
          // and change the duration to 1000
          .then(() => {
            onUpdate({
              ...other,
              id,
              duration: 1000,
              color: "colorSuccess",
              message: "You bought 3 puppies!",
            });
          })
          // If the promise is rejected, inform the user
          // by changing the color to colorError and updating the message
          // The duration is set to 5000
          .catch(() => {
            onUpdate({
              id,
              duration: 5000,
              color: "colorError",
              message: "An error occurred!",
            })
          })
      }
    }
  })

  return (
    <ReactToastSnackProvider methods={methods} renderer={...}>
      <App />
    </ReactToastSnackProvider>
  )
}

To use the custom promise method, just import useToastSnack and call it like any other internal method.

// components/Elsewhere.js
import { useToastSnack } from 'react-toastsnack';

function Elsewhere() {
  const toastSnack = useToastSnack();

  // When the button is clicked, create a new promise
  // to display a loading notification, which will change whenever the request responds

  return (
    <button
      onClick={() => {
        toastSnack.promise({
          promise: fetch(puppies_url, { method: 'POST' }),
        });
      }}
    >
      Click here to buy puppies
    </button>
  );
}

Note that the duration, color and message variables in this example are completely arbitrary.
You have full control over any variables which are not id, open or offset.

dismiss

?boolean: Whether or not we should dismiss active notifications to display new ones, if the max count has been reached.

Default: false

initial

?Array<ToastSnack>: A list of initial notifications.

Default: []

height

?number: The default assumed height for calculating offsets. This can be overwritten by using the onUpdate function.

Default: 48

offset

?number: The offset and distance between notifications.

Default: 8

delay

?number: The transition delay; How long to wait between a dismissal and queueing the next notification.

Default: 400

max

?number: The maximum number of concurrent notifications.

Default: null

Credits

react-toastsnack is built and maintained by babangsund.
@blog.
@github.
@twitter.