Security News
RubyGems.org Adds New Maintainer Role
RubyGems.org has added a new "maintainer" role that allows for publishing new versions of gems. This new permission type is aimed at improving security for gem owners and the service overall.
react-toastify
Advanced tools
The react-toastify package allows developers to add customizable notification toasts to their React applications. It provides an easy way to display success, error, warning, and informational messages with a variety of animations, positions, and options.
Displaying Toast Notifications
This feature allows you to display a simple toast notification with a message. The toast function can be called with a string message to display it to the user.
import { toast } from 'react-toastify';
toast('Hello World!');
Customizing Toast Appearance
This feature allows you to customize the appearance and behavior of the toast. You can specify the type (like success, error, etc.), position, auto-close time, and many other options.
import { toast } from 'react-toastify';
toast.success('Success!', {
position: "top-right",
autoClose: 5000,
hideProgressBar: false,
closeOnClick: true,
pauseOnHover: true,
draggable: true,
progress: undefined,
});
Custom Rendered Components
This feature allows you to render a custom React component inside the toast. This is useful for creating complex toasts with custom layouts and functionality.
import { toast } from 'react-toastify';
const CustomToast = ({ closeToast }) => (
<div>
Something went wrong! <button onClick={closeToast}>Close</button>
</div>
);
toast(<CustomToast />);
Updating Existing Toasts
This feature allows you to update an existing toast's content or appearance. You can change the message, type, or any other property of the toast after it has been displayed.
import { toast } from 'react-toastify';
const toastId = React.useRef(null);
const updateToast = () => {
toast.update(toastId.current, { type: toast.TYPE.INFO, render: 'Updated!' });
};
// Create a toast and save its ID
toastId.current = toast('Initial message');
Controlling Toasts Programmatically
This feature gives you programmatic control over the toasts. You can dismiss all toasts or specific toasts by their ID, which can be useful in scenarios where user actions or other events should close notifications.
import { toast } from 'react-toastify';
// Display a toast
toast('Will close in 5 seconds', { autoClose: 5000 });
// Dismiss all toasts on demand
toast.dismiss();
// Dismiss a specific toast by ID
toast.dismiss(toastId.current);
Notistack is a Snackbar notification library that can be used with Material-UI. It allows for stacking notifications and offers similar customization options. Compared to react-toastify, it is more tightly integrated with Material-UI components and design patterns.
React Notification System is another package for adding notifications to a React app. It provides a different set of customization options and a slightly different API. It is less maintained compared to react-toastify and might not have as many features.
SweetAlert2 with React content is a package for creating beautiful, responsive, customizable, and accessible (WAI-ARIA) replacement for JavaScript's popup boxes with React content. It is more focused on modal dialogs and alerts rather than toasts, but it can be used for similar notification purposes.
š React-Toastify allow you to add notification to your app with ease. No bullshit !
$ npm install --save react-toastify
$ yarn add react-toastify
findDOMNode
or any DOM hackonOpen
and onClose
hooks. Both can access the props passed to the react component rendered inside the toastThe v3 rely on glamor for styling. Using css classes is still fine but you may need to replace your css classes by a glamor rule in some case.
No more css file to import !
A style helper has been added to mimic the old sass variables.
By default all toasts will inherits ToastContainer's props. Props defined on toast supersede ToastContainer's props.
import React, { Component } from 'react';
import { ToastContainer, toast } from 'react-toastify';
class App extends Component {
notify = () => toast("Wow so easy !");
render(){
return (
<div>
<button onClick={this.notify}>Notify !</button>
<ToastContainer />
</div>
);
}
}
By default all the toasts will be positionned on the top right of your browser. If a position is set on a toast, the one defined on ToastContainer will be replaced.
The following values are allowed: top-right, top-center, top-left, bottom-right, bottom-center, bottom-left
For convenience, toast expose a POSITION property to avoid any typo.
// toast.POSITION.TOP_LEFT, toast.POSITION.TOP_RIGHT, toast.POSITION.TOP_CENTER
// toast.POSITION.BOTTOM_LEFT,toast.POSITION.BOTTOM_RIGHT, toast.POSITION.BOTTOM_CENTER
import React, { Component } from 'react';
import { toast } from 'react-toastify';
import { css } from 'glamor';
class Position extends Component {
notify = () => {
toast("Default Notification !");
toast.success("Success Notification !", {
position: toast.POSITION.TOP_CENTER
});
toast.error("Error Notification !", {
position: toast.POSITION.TOP_LEFT
});
toast.warn("Warning Notification !", {
position: toast.POSITION.BOTTOM_LEFT
});
toast.info("Info Notification !", {
position: toast.POSITION.BOTTOM_CENTER
});
toast("Custom Style Notification !", {
position: toast.POSITION.BOTTOM_RIGHT,
className: css({
background: "black"
})
});
};
render(){
return <button onClick={this.notify}>Notify</button>;
}
}
import React from 'react';
import { ToastContainer } from 'react-toastify';
// close toast after 8 seconds
const App = () => (
<ToastContainer autoClose={8000} />
);
import React from 'react';
import { ToastContainer } from 'react-toastify';
class App extends Component {
closeAfter15 = () => toast("YOLO", { autoClose: 15000 });
closeAfter7 = () => toast("7 Kingdoms", { autoClose: 15000 })
render(){
return (
<div>
<button onClick={this.closeAfter15}>Close after 15 seconds</button>
<button onClick={this.closeAfter7}>Close after 7 seconds</button>
<ToastContainer autoClose={8000} />
</div>
);
}
}
{/* Some components */}
<ToastContainer autoClose={false} />
{/* Some components */}
{/* Some components */}
toast("hello", {
autoClose: false
})
{/* Some components */}
When you render a component, a closeToast
function is passed as a props. That way you can close the toast on user interaction for example.
import React from 'react';
import { ToastContainer, toast } from "react-toastify";
const Msg = ({ closeToast }) => (
<div>
Lorem ipsum dolor
<button>Retry</button>
<button onClick={closeToast}>Close</button>
</div>
)
const App = () => (
<div>
<button onClick={() => toast(<Msg />)}>Hello š</button>
<ToastContainer />
</div>
);
An id is returned each time you display a toast, use it to remove a given toast programmatically by calling toast.dismiss(id)
Without args, all the displayed toasts will be removed.
import React, { Component } from 'react';
import { toast } from 'react-toastify';
class Example extends Component {
toastId = null;
notify = () => this.toastId = toast("Lorem ipsum dolor");
dismiss = () => toast.dismiss(this.toastId);
dismissAll = () => toast.dismiss();
render(){
return (
<div>
<button onClick={this.notify}>Notify</button>
<button onClick={this.dismiss}>Dismiss</button>
<button onClick={this.dismissAll}>Dismiss All</button>
</div>
);
}
}
To prevent duplicates, you can check if a given toast is active by calling toast.isActive(id)
like the snippet below. With this approach, you can decide with more precision whether or not you want to display a toast.
import React, { Component } from 'react';
import { toast } from 'react-toastify';
class Example extends Component {
toastId = null;
notify = () => {
if (! toast.isActive(this.toastId)) {
this.toastId = toast("I cannot be duplicated !");
}
}
render(){
return (
<div>
<button onClick={this.notify}>Notify</button>
</div>
);
}
}
You can define two hooks on toast. Hooks are really useful when the toast are not used only to display messages.
import React, { Component } from 'react';
import { toast } from 'react-toastify';
class Hook extends Component {
notify = () => toast(<MyComponent foo="bar" />, {
onOpen: ({ foo }) => window.alert('I counted to infinity once then..'),
onClose: ({ foo }) => window.alert('I counted to infinity twice')
});
render(){
return <button onClick={this.notify}>Notify</button>;
}
}
You can pass a custom close button to the ToastContainer
to replace the default one.
ā ļø When you use a custom close button, your button will receive a closeToast
function.
You need to call it in order to close the toast. ā ļø
import React, { Component } from 'react';
import { toast, ToastContainer } from 'react-toastify';
const CloseButton = ({ YouCanPassAnyProps, closeToast }) => (
<i
className="material-icons"
onClick={closeToast}
>
delete
</i>
);
class CustomClose extends Component {
notify = () => {
toast("The close button change when Chuck Norris display a toast");
};
render(){
return (
<div>
<button onClick={this.notify}>Notify</button>;
<ToastContainer closeButton={<CloseButton YouCanPassAnyProps="foo" />} />
</div>
);
}
}
import React, { Component } from 'react';
import { toast } from 'react-toastify';
// Let's use the closeButton we defined on the previous example
class CustomClose extends Component {
notify = () => {
toast("The close button change when Chuck Norris display a toast",{
closeButton: <CloseButton YouCanPassAnyProps="foo" />
});
};
render(){
return <button onClick={this.notify}>Notify</button>;
}
}
Sometimes you don't want to display a close button. It can be removed globally or per toast. Simply pass
false
to closeButton
props:
{/* Some components */}
<ToastContainer closeButton={false} />
{/* Some components */}
{/* Some components */}
toast("hello", {
closeButton: false
})
{/* Some components */}
See it in action:
const ToastUndo = ({ id, undo, closeToast }) => {
function handleClick(){
undo(id);
closeToast();
}
return (
<div>
<h3>
Row Deleted <button onClick={handleClick}>UNDO</button>
</h3>
</div>
);
}
class App extends Component {
state = {
collection: data,
// Buffer
toRemove: []
};
// Remove the row id from the buffer
undo = id => {
this.setState({
toRemove: this.state.toRemove.filter(v => v !== id)
});
}
// Remove definetly
cleanCollection = () => this.setState({
// Return element which are not included in toRemove
collection: this.state.collection.filter(v => !this.state.toRemove.includes(v.id)),
//Cleanup the buffer
toRemove: []
});
// Remove row from render process
// then display the toast with undo action available
removeRow = e => {
const id = e.target.dataset.rowId;
this.setState({
toRemove: [...this.state.toRemove, id]
});
toast(<ToastUndo undo={this.undo} id={id} />, {
// hook will be called whent the component unmount
onClose: this.cleanCollection
});
};
renderRows() {
const { collection, toRemove } = this.state;
// Render all the element wich are not present in toRemove
// Im using data-attribute to grab the row id
return collection.filter(v => !toRemove.includes(v.id)).map(v => (
<tr key={v.id}>
<td>{v.firstName}</td>
<td>{v.lastName}</td>
<td>{v.email}</td>
<td>
<button onClick={this.removeRow} data-row-id={v.id}>
Delete
</button>
</td>
</tr>
));
}
render() {
// Dont close the toast on click
return (
<div style={styles}>
<table>
<tbody>
<tr>
<th>name</th>
<th>firstname</th>
<th>gender</th>
<th />
</tr>
{this.renderRows()}
</tbody>
</table>
<ToastContainer closeOnClick={false} />
</div>
);
}
}
The toast rely on react-transition-group
for the enter and exit transition.
I'll use the zoom animation from animate.css. Of course, you could create the animation using glamor.
/* style.css*/
@keyframes zoomIn {
from {
opacity: 0;
transform: scale3d(.3, .3, .3);
}
50% {
opacity: 1;
}
}
.zoomIn {
animation-name: zoomIn;
}
@keyframes zoomOut {
from {
opacity: 1;
}
50% {
opacity: 0;
transform: scale3d(.3, .3, .3);
}
to {
opacity: 0;
}
}
.zoomOut {
animation-name: zoomOut;
}
.animate{
animation-duration: 800ms;
}
import React, { Component } from 'react';
import { toast } from 'react-toastify';
import Transition from 'react-transition-group/Transition';
import './style.css';
// Any transition created with react-transition-group/Transition will work !
const ZoomInAndOut = ({ children, position, ...props }) => (
<Transition
{...props}
{/* Same as the animation duration */}
timeout={800}
onEnter={ node => node.classList.add('zoomIn', 'animate')}
onExit={node => {
node.classList.remove('zoomIn', 'animate');
node.classList.add('zoomOut', 'animate');
}}
>
{children}
</Transition>
);
class App extends Component {
notify = () => {
toast("ZoomIn and ZoomOut", {
transition: ZoomInAndOut,
autoClose: 5000
});
};
render(){
return <button onClick={this.notify}>Notify</button>;
}
}
render(){
return(
{/*Component*/}
<ToastContainer
transition={ZoomInAndOut}
/>
{/*Component*/}
);
}
import { style } from "react-toastify";
style({
width: "320px",
colorDefault: "#fff",
colorInfo: "#3498db",
colorSuccess: "#07bc0c",
colorWarning: "#f1c40f",
colorError: "#e74c3c",
colorProgressDefault: "linear-gradient(to right, #4cd964, #5ac8fa, #007aff, #34aadc, #5856d6, #ff2d55)",
mobile: "only screen and (max-width : 480px)",
});
All className like props can be a css class or a glamor rule.
ā ļø Use a glamor rule rather than a css class when you want to override a property cause glamor stylesheet will be injected last ā ļø
import React, { Component } from 'react';
import { toast } from 'react-toastify';
import { css } from 'glamor';
class Style extends Component {
notify = () => {
toast("Dark style notification with default type progress bar",{
className: css({
background: "black"
}),
bodyClassName: "grow-font-size"
});
toast("Fancy progress bar.",{
progressClassName: css({
background: "repeating-radial-gradient(red, yellow 10%, green 15%)"
})
});
};
render(){
return <button onClick={this.notify}>Notify</button>;
}
}
You could define your style gloablly:
render(){
return(
{/*Component*/}
<ToastContainer
toastClassName="dark-toast"
progressClassName={css({
height: "2px"
})}
/>
{/*Component*/}
);
}
On mobile the toast will take all the width available.
Props | Type | Default | Description |
---|---|---|---|
position | string | top-right | One of top-right, top-center, top-left, bottom-right, bottom-center, bottom-left |
autoClose | false or int | 5000 | Delay in ms to close the toast. If set to false, the notification need to be closed manualy |
closeButton | React Element or false | - | A React Component to replace the default close button or false to hide the button |
transition | function | - | A reference to a valid react-transition-group/Transition component |
hideProgressBar | bool | false | Display or not the progress bar below the toast(remaining time) |
pauseOnHover | bool | true | Keep the timer running or not on hover |
closeOnClick | bool | true | Dismiss toast on click |
newestOnTop | bool | false | Display newest toast on top |
className | string|glamor rule | - | Add optional classes to the container |
style | object | - | Add optional inline style to the container |
toastClassName | string|glamor rule | - | Add optional classes to the toast |
bodyClassName | string|glamor rule | - | Add optional classes to the toast body |
progressClassName | string|glamor rule | - | Add optional classes to the progress bar |
All the method of toast return a toastId except dismiss
and isActive
.
The toastId can be used to remove a toast programmatically or to check if the toast is displayed.
Parameter | Type | Required | Description |
---|---|---|---|
content | string or React Element | ā | Element that will be displayed |
options | object | ā | Possible keys : autoClose, type, closeButton, hideProgressBar |
type
: Kind of notification. One of "default", "success", "info", "warning", "error". You can use toast.TYPE.SUCCESS
and so on to avoid any typo.onOpen
: Called inside componentDidMountonClose
: Called inside componentWillUnmountautoClose
: same as ToastContainer.closeButton
: same as ToastContainer.transition
: same as ToastContainer.closeOnClick
: same as ToastContainer.hideProgressBar
: same as ToastContainer.position
: same as ToastContainerpauseOnHover
: same as ToastContainerclassName
: same as ToastContainer toastClassNamebodyClassName
: same as ToastContainerprogressClassName
: same as ToastContainer:warning:ļø Toast options supersede ToastContainer props :warning:
const Img = ({ src }) => <div><img width={48} src={src} /></div>;
const options = {
onOpen: props => console.log(props.foo),
onClose: props => console.log(props.foo),
autoClose: 6000,
closeButton: <FontAwesomeCloseButton />,
type: toast.TYPE.INFO,
hideProgressBar: false,
position: toast.POSITION.TOP_LEFT,
pauseOnHover: true,
transition: MyCustomTransition
};
const toastId = toast(<Img foo={bar}/>, options) // default, type: 'default'
toast.success("Hello", options) // add type: 'success' to options
toast.info("World", options) // add type: 'info' to options
toast.warn(<Img />, options) // add type: 'warning' to options
toast.error(<Img />, options) // add type: 'error' to options
toast.dismiss() // Remove all toasts !
toast.dismiss(toastId) // Remove given toast
toast.isActive(toastId) //Check if a toast is displayed or not
IE 11+ ā | Latest ā | Latest ā | Latest ā | Latest ā | Latest ā |
onClose
callback on the toast was never called. Relate to issue #50This version may introduce breaking changes due to redesign. My apologies.
But, it brings a lots of new and exciting features !
toast.dismiss(toastId)
toast(<div>hello</div>)
closeToast
callback is also passed down to your component.I was storing react component into state which is a bad practice. What should Go in State This is no more the case now. The separation of concern between the data and the view is respected.
Show your š» and support by giving a ā. Any suggestions and pull request are welcome !
Licensed under MIT
FAQs
React notification made easy
The npm package react-toastify receives a total of 923,587 weekly downloads. As such, react-toastify popularity was classified as popular.
We found that react-toastify demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago.Ā It has 0 open source maintainers collaborating on the project.
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.
Security News
RubyGems.org has added a new "maintainer" role that allows for publishing new versions of gems. This new permission type is aimed at improving security for gem owners and the service overall.
Security News
Node.js will be enforcing stricter semver-major PR policies a month before major releases to enhance stability and ensure reliable release candidates.
Security News
Research
Socket's threat research team has detected five malicious npm packages targeting Roblox developers, deploying malware to steal credentials and personal data.