UNPKG

react-toastsnack

Version:

An unopinionated notification queue for React

275 lines (212 loc) 6.81 kB
# react-toastsnack An unopinionated notification queue for React ## Installation Using [npm](https://www.npmjs.com/): $ npm install react-toastsnack Using [yarn](https://yarnpkg.com/): $ yarn add react-toastsnack Then with a module bundler like [webpack](https://webpack.github.io/), use as you would anything else: ```js // 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. ```jsx // 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`](#renderer) _required_ - [`methods`](#methods) _optional_ - [`dismiss`](#dismiss) _optional_ - [`initial`](#initial) _optional_ - [`height`](#height) _optional_ - [`offset`](#offset) _optional_ - [`delay`](#delay) _optional_ - [`max`](#max) _optional_ ### 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](https://material-ui.com/). The `renderer` may look something like this: ```jsx // 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. ```jsx // 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. ```jsx // 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](https://babangsund.com/). [@github](https://github.com/babangsund). [@twitter](https://twitter.com/babangsund).