react 任意页面,调用函数即可生成的一个全局组件

1,154 阅读2分钟

需求

今天有这么一个需求:每一分钟调用一次后台接口,并且监听是在存在告警状态的设备,不论当前处在哪个页面,如果发现有设备处于告警状态,页面中间出现一个提示“xxx温度超过最高临界值”的弹窗,然后用户可以点击弹窗的确认按钮,跳转查看所有的告警设备。

难点是我们不知道用户当前处于哪个页面,但是仔细一想,我们可以去参考一下Ant Design Message组件,所以我们上github看一下 Message源码


可以看出来Message是基于rc-notification包实现的,然后我们再看一下rc-notification文档,文档写的很清楚,也有使用方法:

// content是React.Element类型
var Notification = require('rc-notification');
Notification.newInstance({}, notification => {
  notification.notice({
    content: 'content'
  });
});

如果想要进一步了解notification是怎么实现可以在任意地方调用其函数就能够生成一个组件的,可以参考 这里

我的项目是使用的Antd Design Pro框架的,下面来展示一下我的实现:

安装

npm install rc-notification

组件

/src/components/TemperatureWarning

import { ConfirmModal } from '@/components/modal';
import Notification from 'rc-notification';
let notification = null;
Notification.newInstance({}, n => (notification = n));

const showModal = (data, callback) => {
  // ConfirmModal是我封装的提示框组件
  const content = ConfirmModal(
    () => {
      callback();
    },
    '温度告警',
    '确定',
  );
  notification.notice({
    content,
  });
};

export { showModal };

model

import { pathMatchRegexp } from './../utils/utils';
import { netboxNotice } from '@/services/api/app';
import { showModal } from '@/components/TemperatureWarning';

export default {
  namespace: 'app',
  state: {
    existNotice: false,    noticeData: [],  },
  subscriptions: {
    // subscriptions是在app.start() 时被执行,setup是自定义的名字
    setup({ dispatch }) {
    dispatch({ type: 'queryNotice' });
      setInterval(() => {
        dispatch({ type: 'queryNotice' });      }, 1000 * 60);
    },
  },
  effects: {
   *queryNotice({ payload }, { call, put, select }) {     
         // 如果在根目录/登录页 不发起请求      
        if (pathMatchRegexp(['/', '/user/login'], window.location.pathname)) {        
            return;     
         }      
          // 温度预警     
         const existNotice = yield select(state => {
            return state.app.existNotice; 
         });
         let res = {};
          if (!existNotice) {
            res = yield call(netboxNotice); 
         }
         if (res.data && res.data.length > 0) {
            yield put({
              type: 'showNoticeReducers',
              payload: res.data, 
          });
      } 
   },
  },
 reducers: {
    showNoticeReducers(state, { payload }) {
      return {
        ...state,
        existNotice: true,
        noticeData: payload,
      };
    }, 
   hiddenNoticeReducers(state, { payload }) {
      return {
        ...state,
        existNotice: false,
      };
    },
  },
};

page

/src/layouts/BasicLayout.js

static getDerivedStateFromProps(nextProps, prevState) {    
    const { showNotice, dispatch, noticeData } = nextProps;   
     if (showNotice) {      
         temperatureWarning.showModal(noticeData, () => {       
         // 这里是弹窗确认按钮的回调处理函数,逻辑管理完之后关闭弹窗       
         // do something...        
        dispatch({ type: 'app/hiddenNoticeReducers' 
       });     
     });     
     return;   
    }    
    return null;
}