rendering

Many projects need to implement Toast, the prompt effect common in apps. This effect is deceptively simple and easy to implement. For convenience, it is packaged as an NPM component for subsequent use. React-comment-toast

Method of use

import Toast from "react-common-toast";
Toast.info("xxx");
Toast.info("xxx",duration,onClose);
Copy the code

Component split

  1. The first is to support multiple prompts, different prompts can be customized differently. Call it Notice.
  2. Notice also has a container component outside of it that loads the Notice and exposes some methods to call Toast Notification, which is a singleton.
  3. Finally, the Toast component is responsible for directly generating different notices or destroying notifications. But Toast is just an object, not really a component.

Notification

Notification is a container that contains an array of notices. Then during render, the circular notice generates a segment of DOM nodes and puts them into its own div. It also provides a method to add a notice to the notice and a method to remove the notice from the notice according to the key. Finally, the key is to define a reRwrite method that takes some parameters, dynamically inserts a div into the DOM, then inserts a Notification into that div, and finally returns an object containing several methods that operate on the Notification. (This is the key to dynamic DOM insertion.)

// Notification is the Notice parent, container // is the core of dynamic insertion and removal of DOM nodes // also exposed to Toast to rewrite their own methods import React from"react";
import ReactDOM from "react-dom";
import Notice from "./Notice";
import "./toast.css"; // Count the total number of notices to prevent duplicationletnoticeNumber = 0; // Generate a unique id const getUuid = () => {return "notification-" + new Date().getTime() + "-" + noticeNumber++;
};
exportdefault class Notification extends React.Component { constructor(props) { super(props); This. state = {notice: [], // Store the current notice:true// Whether to display a mask}; } add(notice) {// Add notice // Create a non-redundant key const {notice} = this.state; const key = notice.key ? notice.key : (notice.key = getUuid()); const mask = notice.mask ? notice.mask :false;
    const temp = notices.filter(item => item.key === key).length;

    if(! Temp) {// There is no further notice. this.setState({ notices: notices, hasMask: mask }); }} remove(key) {this.setState(previousState => {return{ notices: previousState.notices.filter(notice => notice.key ! == key) }; }); }getNoticeDOM() {
    const _this = this;
    const { notices } = this.state;
    letresult = []; Notice const closeCallback = () => {// Notice onClose => { _this.remove(notice.key); // If there is an onClose execution passed in by the userif(notice.onClose) notice.onClose(); }; result.push( <Notice key={notice.key} {... notice} onClose={closeCallback} /> ); });return result;
  }
  getMaskDOM() { const { notices, hasMask } = this.state; // There is always only one maskif (notices.length > 0 && hasMask == true)
      return <div className="tips-mask"/ >; }render() { const noticesDOM = this.getNoticeDOM(); Const maskDOM = this.getMaskdom ();return( <div> {/*{maskDOM}*/} {noticesDOM} </div> ); ReWrite = properties => {const {... props } = properties || {};let div = document.createElement("div"); document.body.appendChild(div); const notification = ReactDOM.render(<Notification {... props} />, div);return {
    notice(noticeProps) {
      notification.add(noticeProps);
    },
    removeNotice(key) {
      notification.remove(key);
    },
    destroy() {
      ReactDOM.unmountComponentAtNode(div);
      document.body.removeChild(div);
    },
    component: notification
  };
};
Copy the code

Notice

It accepts parameters, duration, icon, content, etc

// Notice is a timer generated when the component is initialized // an animation is loaded according to the input time and then the input callback is executed // Notice displays and hides absolute control of Notification received from parent component import React from"react";
import classNames from "classnames";
import { PropTypes } from "prop-types";

export default class Notice extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      shouldClose: false// Whether to enable close animation}; }componentDidMount() {
    if (this.props.duration > 0) {
      this.closeTimer = setTimeout(() => { this.close(); }, this.props.duration - 300); // Subtract the disappearing animation by 300 milliseconds}}componentWillUnmount{this.clearCloseTimer() {this.clearCloseTimer(); }clearCloseTimer() {
    if(this.closeTimer) { clearTimeout(this.closeTimer); this.closeTimer = null; }}close{this.clearCloseTimer() {this.clearCloseTimer() {this.clearCloseTimer(); const _this = this; _this.setState({ shouldClose:true });
    this.timer = setTimeout(() => {
      if (this.props.onClose) {
        this.props.onClose();
      }
      clearTimeout(_this.timer);
    }, 300);
  }
  render() {
    const { shouldClose } = this.state;
    return<div className={classNames({ leave: shouldClose })}> {this.props.content} </div> } } Notice.propTypes = { duration: Proptypes. number, // Notice display time Content: proptypes. any, // Notice display content onClose: proptypes. func // display end callback}; Notice.defaultProps = { duration: 3000 };Copy the code

Toast

ReWrite initializing a newNotification with notification. reWrite and keeping the Notification singleton. Then encapsulate a notice method that dynamically changes the newNotification. Finally, several common NOTICE methods are encapsulated and exposed.

import React from "react";
import classNames from "classnames";
import Notification from "./Notification"; The Toast component is special because <Toast /> is not rendered directly in the DOM but inserted dynamically into the pageletnewNotification; // Get a Notification const getNewNotification = () => {// singletons keep the page always having only one Notificationif(! newNotification) { newNotification = Notification.reWrite(); }returnnewNotification; }; Const notice = (content,type, duration = 3000, onClose, mask = true) = > {if(! content)return;

//   content = content.toString();

  let notificationInstance = getNewNotification();

  notificationInstance.notice({
    duration,
    mask: mask,
    content: (
      <div className={classNames(["tips-notice-box"])}>
        <div
          className={classNames([
            "tips-notice-content",
            { info: type= = ="info" },
            { success: type= = ="success" },
            { warning: type= = ="warning" },
            { error: type= = ="error" }
          ])}
        >
          {content}
        </div>
      </div>
    ),
    onClose: () => {
      if(onClose) onClose(); }}); };export default {
  show(content, duration, icon, mask, onClose) {
    return notice(content, undefined, icon, duration, onClose, mask);
  },
  info(content, duration, icon, mask, onClose) {
    return notice(content, "info", icon, duration, onClose, mask);
  },
  success(content, duration, icon, mask, onClose) {
    return notice(content, "success", icon, duration, onClose, mask);
  },
  warning(content, duration, icon, mask, onClose) {
    return notice(content, "warning", icon, duration, onClose, mask);
  },
  error(content, duration, icon, mask, onClose) {
    return notice(content, "error", icon, duration, onClose, mask);
  },
  hide() {
    if(newNotification) { newNotification.destroy(); newNotification = null; }}};Copy the code