Merge pull request #199 from TinyAllen/master

Update: TraceStack
diff --git a/src/components/Authorized/PromiseRender.js b/src/components/Authorized/PromiseRender.js
index 3d2794f..5034a99 100644
--- a/src/components/Authorized/PromiseRender.js
+++ b/src/components/Authorized/PromiseRender.js
@@ -25,21 +25,23 @@
   };
 
   async componentDidMount() {
-    this.props.promise
+    const {...propsData} =  this.props;
+      propsData.promise
       .then(() => {
         this.setState({
-          component: this.props.ok,
+          component: propsData.ok,
         });
       })
       .catch(() => {
         this.setState({
-          component: this.props.error,
+          component: propsData.error,
         });
       });
   }
 
   render() {
-    const C = this.state.component;
+    const {...stateData} =  this.state;
+    const C = stateData.component;
     return C ? (
       <C {...this.props} />
     ) : (
diff --git a/src/components/Charts/Area/index.js b/src/components/Charts/Area/index.js
index 01c62a1..98107c4 100644
--- a/src/components/Charts/Area/index.js
+++ b/src/components/Charts/Area/index.js
@@ -42,6 +42,14 @@
     window.removeEventListener('resize', this.resize);
   }
 
+  handleRoot = n => {
+    this.root = n;
+  };
+
+  handleRef = n => {
+    this.node = n;
+  };
+
   @Bind()
   @Debounce(200)
   resize() {
@@ -67,15 +75,7 @@
       });
     }
   }
-
-  handleRoot = n => {
-    this.root = n;
-  };
-
-  handleRef = n => {
-    this.node = n;
-  };
-
+  
   render() {
     const { height, title, forceFit = true, data, color, limitColor } = this.props;
 
diff --git a/src/components/Charts/Bar/index.js b/src/components/Charts/Bar/index.js
index 645a36d..7456ea0 100644
--- a/src/components/Charts/Bar/index.js
+++ b/src/components/Charts/Bar/index.js
@@ -36,6 +36,14 @@
     window.removeEventListener('resize', this.resize);
   }
 
+  handleRoot = n => {
+    this.root = n;
+  };
+
+  handleRef = n => {
+    this.node = n;
+  };
+  
   @Bind()
   @Debounce(400)
   resize() {
@@ -63,14 +71,6 @@
     }
   }
 
-  handleRoot = n => {
-    this.root = n;
-  };
-
-  handleRef = n => {
-    this.node = n;
-  };
-
   render() {
     const {
       height,
diff --git a/src/components/Charts/ChartCard/index.js b/src/components/Charts/ChartCard/index.js
index 2801d92..0ef484a 100644
--- a/src/components/Charts/ChartCard/index.js
+++ b/src/components/Charts/ChartCard/index.js
@@ -45,7 +45,7 @@
           </div>
           {// eslint-disable-next-line
           total !== undefined && (
-            <div className={styles.total} dangerouslySetInnerHTML={{ __html: total }} />
+            <div className={styles.total}>{total}</div>
           )}
         </div>
       </div>
diff --git a/src/components/Charts/HeatMap/index.js b/src/components/Charts/HeatMap/index.js
index e36e716..a83c3c7 100644
--- a/src/components/Charts/HeatMap/index.js
+++ b/src/components/Charts/HeatMap/index.js
@@ -56,6 +56,7 @@
     reducedData.map((count, i) => ({ datetime, responseTime: i, count }));
 
   handlePlotClick = (dtStart, dtEnd, responseTime) => {
+    const {...propsData} = this.props
     const removedUnit = responseTime.slice(0, responseTime.indexOf('ms'));
     let min;
     let max;
@@ -66,7 +67,7 @@
       min = value - 100 < 0 ? 0 : value - 100;
       max = value;
     }
-    this.props.onClick({ start: dtStart, end: dtEnd }, { min, max });
+    propsData.onClick({ start: dtStart, end: dtEnd }, { min, max });
   };
 
   render() {
diff --git a/src/components/Charts/Line/index.js b/src/components/Charts/Line/index.js
index 9ac23da..54a985e 100644
--- a/src/components/Charts/Line/index.js
+++ b/src/components/Charts/Line/index.js
@@ -38,6 +38,14 @@
     window.removeEventListener('resize', this.resize);
   }
 
+  handleRoot = n => {
+    this.root = n;
+  };
+
+  handleRef = n => {
+    this.node = n;
+  };
+
   @Bind()
   @Debounce(200)
   resize() {
@@ -64,14 +72,6 @@
     }
   }
 
-  handleRoot = n => {
-    this.root = n;
-  };
-
-  handleRef = n => {
-    this.node = n;
-  };
-
   render() {
     const { height, title, forceFit = true, data } = this.props;
 
diff --git a/src/components/Charts/Pie/index.js b/src/components/Charts/Pie/index.js
index 8c3938e..44c2c5a 100644
--- a/src/components/Charts/Pie/index.js
+++ b/src/components/Charts/Pie/index.js
@@ -42,12 +42,14 @@
   }
 
   componentWillReceiveProps(nextProps) {
-    if (this.props.data !== nextProps.data) {
+    const {...propsData} = this.props;
+    const {...stateData} = this.state;
+    if (propsData.data !== nextProps.data) {
       // because of charts data create when rendered
       // so there is a trick for get rendered time
       this.setState(
         {
-          legendData: [...this.state.legendData],
+          legendData: [...stateData.legendData],
         },
         () => {
           this.getLengendData();
@@ -84,28 +86,6 @@
     });
   };
 
-  // for window resize auto responsive legend
-  @Bind()
-  @Debounce(300)
-  resize() {
-    const { hasLegend } = this.props;
-    if (!hasLegend || !this.root) {
-      window.removeEventListener('resize', this.resize);
-      return;
-    }
-    if (this.root.parentNode.clientWidth <= 380) {
-      if (!this.state.legendBlock) {
-        this.setState({
-          legendBlock: true,
-        });
-      }
-    } else if (this.state.legendBlock) {
-      this.setState({
-        legendBlock: false,
-      });
-    }
-  }
-
   handleRoot = n => {
     this.root = n;
   };
@@ -128,6 +108,29 @@
     });
   };
 
+// for window resize auto responsive legend
+@Bind()
+@Debounce(300)
+resize() {
+  const {...stateData} = this.state;
+  const { hasLegend } = this.props;
+  if (!hasLegend || !this.root) {
+    window.removeEventListener('resize', this.resize);
+    return;
+  }
+  if (this.root.parentNode.clientWidth <= 380) {
+    if (!stateData.legendBlock) {
+      this.setState({
+        legendBlock: true,
+      });
+    }
+  } else if (stateData.legendBlock) {
+    this.setState({
+      legendBlock: false,
+    });
+  }
+}
+
   render() {
     const {
       valueFormat,
@@ -151,11 +154,11 @@
       [styles.hasLegend]: !!hasLegend,
       [styles.legendBlock]: legendBlock,
     });
-
+    const {...propsData} = this.props;
     const defaultColors = colors;
-    let data = this.props.data || [];
-    let selected = this.props.selected || true;
-    let tooltip = this.props.tooltip || true;
+    let data = propsData.data || [];
+    let selected = propsData.selected || true;
+    let tooltip = propsData.tooltip || true;
     let formatColor;
 
     const scale = {
diff --git a/src/components/Charts/StackBar/index.js b/src/components/Charts/StackBar/index.js
index bdec13a..0180b0f 100644
--- a/src/components/Charts/StackBar/index.js
+++ b/src/components/Charts/StackBar/index.js
@@ -42,6 +42,14 @@
     window.removeEventListener('resize', this.resize);
   }
 
+  handleRoot = n => {
+    this.root = n;
+  };
+
+  handleRef = n => {
+    this.node = n;
+  };
+
   @Bind()
   @Debounce(200)
   resize() {
@@ -68,14 +76,6 @@
     }
   }
 
-  handleRoot = n => {
-    this.root = n;
-  };
-
-  handleRef = n => {
-    this.node = n;
-  };
-
   render() {
     const { height, title, forceFit = true, data, color, limitColor } = this.props;
 
diff --git a/src/components/Duration/Icon/index.js b/src/components/Duration/Icon/index.js
index 4d4bbd7..999350b 100644
--- a/src/components/Duration/Icon/index.js
+++ b/src/components/Duration/Icon/index.js
@@ -35,8 +35,9 @@
   };
 
   renderLoad() {
+    const {...stateData} = this.state;
     const { loading, className, onReload } = this.props;
-    if (!loading && this.state.innerLoading < 1) {
+    if (!loading && stateData.innerLoading < 1) {
       this.state.innerLoading = -1;
       return (
         <span className={className} onClick={onReload}>
@@ -45,7 +46,7 @@
         </span>
       );
     }
-    if (this.state.innerLoading < 0) {
+    if (stateData.innerLoading < 0) {
       this.state.innerLoading = 1;
       lodash.delay(() => this.setState({ innerLoading: 0 }), 1000);
     }
diff --git a/src/components/Duration/Panel/currentTimePanel.js b/src/components/Duration/Panel/currentTimePanel.js
index e063776..93b0e09 100644
--- a/src/components/Duration/Panel/currentTimePanel.js
+++ b/src/components/Duration/Panel/currentTimePanel.js
@@ -15,7 +15,7 @@
  * limitations under the License.
  */
 
-import React, { PureComponent } from 'react';
+import { PureComponent } from 'react';
 
 class CurrentTimePanel extends PureComponent {
   state = {
diff --git a/src/components/Duration/Panel/index.js b/src/components/Duration/Panel/index.js
index a8a7565..56f20a3 100644
--- a/src/components/Duration/Panel/index.js
+++ b/src/components/Duration/Panel/index.js
@@ -178,15 +178,16 @@
   };
 
   handleTimeZone = (zone) => {
-    this.props.dispatch({
+    const {...propsData} = this.props;
+    propsData.dispatch({
       type: 'global/changeTimezone',
       payload: zone,
     });
-    this.props.dispatch({
+    propsData.dispatch({
       type: 'trace/changeTimezone',
       payload: zone,
     });
-    this.select(this.props.selected);
+    this.select(propsData.selected);
   }
 
   select = newSelectedTime => {
diff --git a/src/components/Login/LoginItem.js b/src/components/Login/LoginItem.js
index 52d5a4a..364a71c 100644
--- a/src/components/Login/LoginItem.js
+++ b/src/components/Login/LoginItem.js
@@ -40,8 +40,10 @@
       }
 
       componentDidMount() {
-        if (this.context.updateActive) {
-          this.context.updateActive(this.props.name);
+        const {...contextData} = this.context;
+        const {...propsData} = this.props;
+        if (contextData.updateActive) {
+          contextData.updateActive(propsData.name);
         }
       }
 
@@ -51,9 +53,10 @@
 
       onGetCaptcha = () => {
         let count = 59;
+        const {...propsData} = this.props;
         this.setState({ count });
-        if (this.props.onGetCaptcha) {
-          this.props.onGetCaptcha();
+        if (propsData.onGetCaptcha) {
+          propsData.onGetCaptcha();
         }
         this.interval = setInterval(() => {
           count -= 1;
@@ -65,7 +68,8 @@
       };
 
       render() {
-        const { getFieldDecorator } = this.context.form;
+        const {...contextData} = this.context;
+        const { getFieldDecorator } = contextData.form;
         const options = {};
         let otherProps = {};
         const { onChange, defaultValue, rules, name, ...restProps } = this.props;
diff --git a/src/components/Login/LoginTab.js b/src/components/Login/LoginTab.js
index 3d56eb7..a655339 100644
--- a/src/components/Login/LoginTab.js
+++ b/src/components/Login/LoginTab.js
@@ -42,8 +42,9 @@
   }
 
   componentWillMount() {
-    if (this.context.tabUtil) {
-      this.context.tabUtil.addTab(this.uniqueId);
+    const {...contextData} = this.context;
+    if (contextData.tabUtil) {
+      contextData.tabUtil.addTab(this.uniqueId);
     }
   }
 
diff --git a/src/components/Login/index.js b/src/components/Login/index.js
index 6e765f9..938b0d6 100644
--- a/src/components/Login/index.js
+++ b/src/components/Login/index.js
@@ -46,26 +46,28 @@
   };
 
   state = {
-    type: this.props.defaultActiveKey,
+    type: '',
     tabs: [],
     active: {},
   };
 
   getChildContext() {
+    const {...stateData} = this.state;
+    const {...propsData} = this.props;
     return {
       tabUtil: {
         addTab: (id) => {
           this.setState({
-            tabs: [...this.state.tabs, id],
+            tabs: [...stateData.tabs, id],
           });
         },
         removeTab: (id) => {
           this.setState({
-            tabs: this.state.tabs.filter(currentId => currentId !== id),
+            tabs: stateData.tabs.filter(currentId => currentId !== id),
           });
         },
       },
-      form: this.props.form,
+      form: propsData.form,
       updateActive: (activeItem) => {
         const { type, active } = this.state;
         if (active[type]) {
@@ -80,19 +82,26 @@
     };
   }
 
+  componentWillMount() {
+    const {...propsData} = this.props;
+    this.setState({ type: propsData.defaultActiveKey });
+  };
+
   onSwitch = (type) => {
+    const {...propsData} = this.props;
     this.setState({
       type,
     });
-    this.props.onTabChange(type);
+    propsData.onTabChange(type);
   };
 
   handleSubmit = (e) => {
     e.preventDefault();
+    const {...propsData} = this.props;
     const { active, type } = this.state;
     const activeFileds = active[type];
-    this.props.form.validateFields(activeFileds, { force: true }, (err, values) => {
-      this.props.onSubmit(err, values);
+    propsData.form.validateFields(activeFileds, { force: true }, (err, values) => {
+      propsData.onSubmit(err, values);
     });
   };
 
diff --git a/src/components/NoticeIcon/index.js b/src/components/NoticeIcon/index.js
index b3da0a7..3f1b0f1 100644
--- a/src/components/NoticeIcon/index.js
+++ b/src/components/NoticeIcon/index.js
@@ -54,12 +54,14 @@
   }
 
   onTabChange = (tabType) => {
+    const {...propsData} = this.props;
     this.setState({ tabType });
-    this.props.onTabChange(tabType);
+    propsData.onTabChange(tabType);
   }
 
   getNotificationBox() {
     const { children, loading, locale } = this.props;
+    const {...propsData} = this.props;
     if (!children) {
       return null;
     }
@@ -72,7 +74,7 @@
             {...child.props}
             data={child.props.list}
             onClick={item => this.onItemClick(item, child.props)}
-            onClear={() => this.props.onClear(child.props.title)}
+            onClear={() => propsData.onClear(child.props.title)}
             title={child.props.title}
             locale={locale}
           />
@@ -103,8 +105,9 @@
       return trigger;
     }
     const popoverProps = {};
+    const {...propsData} = this.props;
     if ('popupVisible' in this.props) {
-      popoverProps.visible = this.props.popupVisible;
+      popoverProps.visible = propsData.popupVisible;
     }
     return (
       <Popover
diff --git a/src/components/Page/Panel/index.js b/src/components/Page/Panel/index.js
index 30bdf07..a80d9ed 100644
--- a/src/components/Page/Panel/index.js
+++ b/src/components/Page/Panel/index.js
@@ -27,11 +27,12 @@
   }
 
   shouldComponentUpdate(nextProps) {
+    const {...propsData} = this.props;
     const { globalVariables, variables, onChange } = nextProps;
     if (!this.isRender(nextProps)) {
       return false;
     }
-    if (globalVariables !== this.props.globalVariables || variables !== this.props.variables) {
+    if (globalVariables !== propsData.globalVariables || variables !== propsData.variables) {
       onChange({ ...globalVariables, ...variables });
       return false;
     }
diff --git a/src/components/Page/Search/index.js b/src/components/Page/Search/index.js
index c47cabe..31ecfe4 100644
--- a/src/components/Page/Search/index.js
+++ b/src/components/Page/Search/index.js
@@ -36,14 +36,16 @@
   };
 
   componentDidMount() {
-    if (this.props.variables && Object.keys(this.props.variables).length > 0) {
-      this.originFetchServer('', this.props.value.key);
+    const {...propsData} = this.props;
+    if (propsData.variables && Object.keys(propsData.variables).length > 0) {
+      this.originFetchServer('', propsData.value.key);
     }
   }
 
   componentDidUpdate(prevProps) {
-    if (prevProps.variables !== this.props.variables) {
-      this.originFetchServer('', this.props.value.key);
+    const {...propsData} = this.props;
+    if (prevProps.variables !== propsData.variables) {
+      this.originFetchServer('', propsData.value.key);
     }
   }
 
@@ -52,6 +54,7 @@
       return;
     }
     const { url, query, variables = {}, transform } = this.props;
+    const {...stateData} = this.state;
     this.lastFetchId += 1;
     const fetchId = this.lastFetchId;
     this.setState({ data: [], fetching: true });
@@ -71,41 +74,43 @@
       }
       const list = body.data[Object.keys(body.data)[0]];
       this.setState({ data: transform ? list.map(transform) : list, fetching: false });
-      if (this.state.data.length < 1) {
+      if (stateData.data.length < 1) {
         return;
       }
       if (!key) {
-        this.handleSelect(this.state.data[0]);
+        this.handleSelect(stateData.data[0]);
         return;
       }
-      const option = this.state.data.find(_ => _.key === key);
+      const option = stateData.data.find(_ => _.key === key);
       if (!option) {
-        this.handleSelect(this.state.data[0]);
+        this.handleSelect(stateData.data[0]);
       }
     });
   };
 
   handleSelect = value => {
     const { onSelect } = this.props;
-    const selected = this.state.data.find(_ => _.key === value.key);
+    const { ...stateData } = this.state;
+    const selected = stateData.data.find(_ => _.key === value.key);
     onSelect(selected);
   };
 
   render() {
     const { placeholder, value } = this.props;
+    const { ...stateData } = this.state;
     return (
       <Select
         showSearch
         style={{ width: 600 }}
         placeholder={placeholder}
-        notFoundContent={this.state.fetching ? <Spin size="small" /> : null}
+        notFoundContent={stateData.fetching ? <Spin size="small" /> : null}
         filterOption={false}
         labelInValue
         onSelect={this.handleSelect.bind(this)}
         onSearch={this.fetchServer}
         value={value}
       >
-        {this.state.data.map(_ => {
+        {stateData.data.map(_ => {
           return (
             <Option key={_.key} value={_.key}>
               {_.label}
diff --git a/src/components/SiderMenu/SiderMenu.js b/src/components/SiderMenu/SiderMenu.js
index ca6ff3f..10229e7 100644
--- a/src/components/SiderMenu/SiderMenu.js
+++ b/src/components/SiderMenu/SiderMenu.js
@@ -52,7 +52,8 @@
   }
 
   componentWillReceiveProps(nextProps) {
-    if (nextProps.location.pathname !== this.props.location.pathname) {
+    const {...propsData} = this.props;
+    if (nextProps.location.pathname !== propsData.location.pathname) {
       this.setState({
         openKeys: this.getDefaultCollapsedSubMenus(nextProps),
       });
@@ -126,6 +127,7 @@
   * @memberof SiderMenu
   */
   getMenuItemPath = (item) => {
+    const {...propsData} = this.props;
     const itemPath = this.conversionPath(item.path);
     const icon = getIcon(item.icon);
     const { target, name } = item;
@@ -141,8 +143,8 @@
       <Link
         to={itemPath}
         target={target}
-        replace={itemPath === this.props.location.pathname}
-        onClick={() => this.props.onCollapse(true)}
+        replace={itemPath === propsData.location.pathname}
+        onClick={() => propsData.onCollapse(true)}
       >
         {icon}<span>{name}</span>
       </Link>
@@ -206,8 +208,9 @@
 
   // permission to check
   checkPermissionItem = (authority, ItemDom) => {
-    if (this.props.Authorized && this.props.Authorized.check) {
-      const { check } = this.props.Authorized;
+    const {...propsData} = this.props;
+    if (propsData.Authorized && propsData.Authorized.check) {
+      const { check } = propsData.Authorized;
       return check(
         authority,
         ItemDom
diff --git a/src/components/Topology/AppTopology.js b/src/components/Topology/AppTopology.js
index e3f944e..1568f69 100644
--- a/src/components/Topology/AppTopology.js
+++ b/src/components/Topology/AppTopology.js
@@ -90,7 +90,7 @@
     const layer = cy.cyCanvas();
     const canvas = layer.getCanvas();
     
-    cy.on('render cyCanvas.resize', (evt) => {
+    cy.on('render cyCanvas.resize', () => {
       const ctx = canvas.getContext('2d');
       layer.resetTransform(ctx);
       layer.clear(ctx);
diff --git a/src/components/TraceStack/index.js b/src/components/TraceStack/index.js
index a4bfd7e..53ecfbb 100644
--- a/src/components/TraceStack/index.js
+++ b/src/components/TraceStack/index.js
@@ -259,20 +259,22 @@
   }
 
   selectTimeline = (container, isOver) => {
-    if (this.state.container === container) {
+    const {...stateData} = this.state;
+    if (stateData.container === container) {
       return;
     }
     container.attr('class', isOver ? styles.backgroud : styles.backgroudHide);
   }
 
   showSpanModal = (span, position, container) => {
+    const {...stateData} = this.state;
     const { container: old } = this.state;
     if (old) {
       old.attr('class', styles.backgroudHide);
     }
     container.attr('class', styles.backgroudSelected);
     this.setState({
-      ...this.state,
+      ...stateData,
       span,
       key: 'tags',
       position,
@@ -282,29 +284,31 @@
 
   hideSpanModal = () => {
     const { container: old } = this.state;
+    const {...stateData} = this.state;
     if (old) {
       old.attr('class', styles.backgroudHide);
     }
     this.setState({
-      ...this.state,
+      ...stateData,
       span: {},
       container: undefined,
     });
   }
 
   resize = () => {
+    const {...stateData} = this.state;
     if (!this.axis) {
       return;
     }
-    this.state.width = this.axis.parentNode.clientWidth - 50;
-    if (!this.axis || this.state.width <= 0) {
+    this.setState({width:this.axis.parentNode.clientWidth - 50});
+    if (!this.axis || stateData.width <= 0) {
       return;
     }
     this.axis.innerHTML = '';
     this.duration.innerHTML = '';
     this.drawAxis();
     this.displayData();
-    this.setState({ ...this.state, span: {} });
+    this.setState({ ...stateData, span: {} });
   }
 
   renderTitle = (items) => {
@@ -400,7 +404,7 @@
         </DescriptionList>);
     }
     const { top, left, width } = position;
-
+    const {...stateData} = this.state;
     const toolTipStyle = { position: 'absolute', top: top + 86 };
     if (contentList.logs) {
       toolTipStyle.left = 0;
@@ -440,7 +444,7 @@
             style={toolTipStyle}
             extra={<Button type="primary" shape="circle" icon="close" ghost onClick={this.hideSpanModal} />}
           >
-            {contentList[this.state.key]}
+            {contentList[stateData.key]}
           </Card>
         ) : null}
       </div>
diff --git a/src/layouts/BasicLayout.js b/src/layouts/BasicLayout.js
index ead1f91..1ea9595 100644
--- a/src/layouts/BasicLayout.js
+++ b/src/layouts/BasicLayout.js
@@ -90,6 +90,7 @@
   }
 
   componentWillUpdate(nextProps) {
+    const {...propsData} = this.props;
     const { globalVariables: { duration }, isMonitor } = nextProps;
     if (!isMonitor) {
       return;
@@ -101,7 +102,7 @@
     if (duration === preDuration) {
       return;
     }
-    this.props.dispatch({
+    propsData.dispatch({
       type: 'global/fetchNotice',
       payload: { variables: { duration } },
     });
@@ -133,20 +134,23 @@
   }
 
   handleDurationToggle = () => {
-    this.props.dispatch({
+    const {...propsData} = this.props;
+    propsData.dispatch({
       type: 'global/changeDurationCollapsed',
-      payload: this.props.duration.collapsed,
+      payload: propsData.duration.collapsed,
     });
   }
 
   handleDurationReload = () => {
-    this.props.dispatch({
+    const {...propsData} = this.props;
+    propsData.dispatch({
       type: 'global/reloadDuration',
     });
   }
 
   handleDurationSelected = (selectedDuration) => {
-    this.props.dispatch({
+    const {...propsData} = this.props;
+    propsData.dispatch({
       type: 'global/changeDuration',
       payload: selectedDuration,
     });
@@ -161,27 +165,30 @@
   }
 
   handleMenuCollapse = (collapsed) => {
-    this.props.dispatch({
+    const {...propsData} = this.props;
+    propsData.dispatch({
       type: 'global/changeLayoutCollapsed',
       payload: collapsed,
     });
   }
 
   handleMenuClick = ({ key }) => {
+    const {...propsData} = this.props;
     if (key === 'triggerError') {
-      this.props.dispatch(routerRedux.push('/exception/trigger'));
+      propsData.dispatch(routerRedux.push('/exception/trigger'));
       return;
     }
     if (key === 'logout') {
-      this.props.dispatch({
+      propsData.dispatch({
         type: 'login/logout',
       });
     }
   }
 
   handleNoticeVisibleChange = (visible) => {
+    const {...propsData} = this.props;
     if (visible) {
-      this.props.dispatch({
+      propsData.dispatch({
         type: 'global/fetchNotices',
       });
     }
@@ -196,6 +203,7 @@
   }
 
   render() {
+    const {...propsData} = this.props;
     const {
       isMonitor, collapsed, fetching, notices, routerData, match, location, zone,
       duration: { selected: dSelected, collapsed: dCollapsed },
@@ -235,7 +243,7 @@
               onSelected={this.handleDurationSelected}
               collapsed={dCollapsed}
               zone={zone}
-              dispatch={this.props.dispatch}
+              dispatch={propsData.dispatch}
             />
           ) : null}
           <Content style={{ margin: '24px 24px 0', height: '100%' }}>
diff --git a/src/routes/Alarm/Alarm.js b/src/routes/Alarm/Alarm.js
index a5aa771..9da9e8a 100644
--- a/src/routes/Alarm/Alarm.js
+++ b/src/routes/Alarm/Alarm.js
@@ -44,9 +44,10 @@
 }))
 export default class Alarm extends PureComponent {
   componentDidMount() {
+    const {...propsData} = this.props;
     const { alarm: { variables: { values } } } = this.props;
     if (!values.scope) {
-      this.props.dispatch({
+      propsData.dispatch({
         type: 'alarm/saveVariables',
         payload: { values: {
           scope: 'Service',
@@ -57,7 +58,8 @@
   }
 
   handleSearch = (keyword) => {
-    this.props.dispatch({
+    const {...propsData} = this.props;
+    propsData.dispatch({
       type: 'alarm/saveVariables',
       payload: { values: {
         keyword,
@@ -67,7 +69,8 @@
   }
 
   handlePageChange = (pag) => {
-    this.props.dispatch({
+    const {...propsData} = this.props;
+    propsData.dispatch({
       type: 'alarm/saveVariables',
       payload: { values: {
         paging: {
@@ -80,7 +83,8 @@
   }
 
   changeScope = (scope) => {
-    this.props.dispatch({
+    const {...propsData} = this.props;
+    propsData.dispatch({
       type: 'alarm/saveVariables',
       payload: { values: {
         scope,
@@ -90,8 +94,9 @@
   }
 
   handleChange = (variables) => {
+    const {...propsData} = this.props;
     const { paging = defaultPaging } = variables;
-    this.props.dispatch({
+    propsData.dispatch({
       type: 'alarm/fetchData',
       payload: { variables: { ...variables, paging }, reducer: funcMap[variables.scope] },
     });
@@ -138,11 +143,12 @@
         />
       </div>
     );
+    const {...propsData} = this.props;
     const { alarm: { variables: { values }, data } } = this.props;
     return (
       <Panel
         variables={values}
-        globalVariables={this.props.globalVariables}
+        globalVariables={propsData.globalVariables}
         onChange={this.handleChange}
       >
         <Card
diff --git a/src/routes/Endpoint/Endpoint.js b/src/routes/Endpoint/Endpoint.js
index 278b97b..49f07df 100644
--- a/src/routes/Endpoint/Endpoint.js
+++ b/src/routes/Endpoint/Endpoint.js
@@ -20,7 +20,7 @@
 import { connect } from 'dva';
 import { Row, Col, Form, Button, Icon, Select } from 'antd';
 import {
-  ChartCard, MiniArea, MiniBar, Sankey, Line, EndpointDeps,
+  ChartCard, MiniArea, MiniBar, Line, EndpointDeps,
 } from 'components/Charts';
 import { axisY, axisMY } from '../../utils/time';
 import { avgTS } from '../../utils/utils';
@@ -52,24 +52,27 @@
 })
 export default class Endpoint extends PureComponent {
   componentDidMount() {
-    this.props.dispatch({
+    const {...propsData} = this.props;
+    propsData.dispatch({
       type: 'endpoint/initOptions',
-      payload: { variables: this.props.globalVariables, reducer: 'saveServiceInfo' },
+      payload: { variables: propsData.globalVariables, reducer: 'saveServiceInfo' },
     });
   }
 
   componentWillUpdate(nextProps) {
-    if (nextProps.globalVariables.duration === this.props.globalVariables.duration) {
+    const {...propsData} = this.props;
+    if (nextProps.globalVariables.duration === propsData.globalVariables.duration) {
       return;
     }
-    this.props.dispatch({
+    propsData.dispatch({
       type: 'endpoint/initOptions',
       payload: { variables: nextProps.globalVariables, reducer: 'saveServiceInfo' },
     });
   }
 
   handleServiceSelect = (selected) => {
-    this.props.dispatch({
+    const {...propsData} = this.props;
+    propsData.dispatch({
       type: 'endpoint/save',
       payload: {
         variables: {
@@ -84,7 +87,8 @@
   }
 
   handleSelect = (selected) => {
-    this.props.dispatch({
+    const {...propsData} = this.props;
+    propsData.dispatch({
       type: 'endpoint/save',
       payload: {
         variables: {
@@ -99,7 +103,8 @@
   }
 
   handleChange = (variables) => {
-    const { variables: { values } } = this.props.endpoint;
+    const {...propsData} = this.props;
+    const { variables: { values } } = propsData.endpoint;
     if (!values.serviceId) {
       return;
     }
@@ -107,7 +112,7 @@
     if (!endpointId) {
       return;
     }
-    this.props.dispatch({
+    propsData.dispatch({
       type: 'endpoint/fetchData',
       payload: { variables: {
         endpointId,
@@ -158,17 +163,18 @@
   edgeWith = edge => edge.cpm;
 
   renderPanel = () => {
+    const {...propsData} = this.props;
     const { endpoint, duration } = this.props;
     const { variables: { values }, data } = endpoint;
     const { getEndpointResponseTimeTrend, getEndpointThroughputTrend,
-      getEndpointSLATrend, getEndpointTopology, queryBasicTraces } = data;
+      getEndpointSLATrend, queryBasicTraces } = data;
     if (!values.endpointId) {
       return null;
     }
     return (
       <Panel
         variables={data.endpointInfo}
-        globalVariables={this.props.globalVariables}
+        globalVariables={propsData.globalVariables}
         onChange={this.handleChange}
       >
         <Row gutter={8}>
@@ -216,7 +222,7 @@
             >
               <Line
                 height={150}
-                data={axisMY(this.props.duration, [{ title: 'p99', value: data.getP99}, { title: 'p95', value: data.getP95}
+                data={axisMY(propsData.duration, [{ title: 'p99', value: data.getP99}, { title: 'p95', value: data.getP95}
                 , { title: 'p90', value: data.getP90}, { title: 'p75', value: data.getP75}, { title: 'p50', value: data.getP50}])}
               />
             </ChartCard>
@@ -244,7 +250,7 @@
               <TraceList
                 data={queryBasicTraces.traces}
                 onClickTraceTag={this.handleShowTrace}
-                loading={this.props.loading}
+                loading={propsData.loading}
               />
             </ChartCard>
           </Col>
diff --git a/src/routes/Service/Service.js b/src/routes/Service/Service.js
index ce4c149..9378a95 100644
--- a/src/routes/Service/Service.js
+++ b/src/routes/Service/Service.js
@@ -57,24 +57,27 @@
 })
 export default class Service extends PureComponent {
   componentDidMount() {
-    this.props.dispatch({
+    const {...propsData} = this.props;
+    propsData.dispatch({
       type: 'service/initOptions',
-      payload: { variables: this.props.globalVariables },
+      payload: { variables: propsData.globalVariables },
     });
   }
 
   componentWillUpdate(nextProps) {
-    if (nextProps.globalVariables.duration === this.props.globalVariables.duration) {
+    const {...propsData} = this.props;
+    if (nextProps.globalVariables.duration === propsData.globalVariables.duration) {
       return;
     }
-    this.props.dispatch({
+    propsData.dispatch({
       type: 'service/initOptions',
       payload: { variables: nextProps.globalVariables },
     });
   }
 
   handleSelect = (selected) => {
-    this.props.dispatch({
+    const {...propsData} = this.props;
+    propsData.dispatch({
       type: 'service/saveVariables',
       payload: {
         values: { serviceId: selected.key },
@@ -84,11 +87,12 @@
   }
 
   handleChange = (variables) => {
-    const { data: { serviceInstanceInfo, showServiceInstance } } = this.props.service;
+    const {...propsData} = this.props;
+    const { data: { serviceInstanceInfo, showServiceInstance } } = propsData.service;
     if (showServiceInstance) {
       this.handleSelectServiceInstance(serviceInstanceInfo.key, serviceInstanceInfo);
     } else {
-      this.props.dispatch({
+      propsData.dispatch({
         type: 'service/fetchData',
         payload: { variables, reducer: 'saveService' },
       });
@@ -96,28 +100,32 @@
   }
 
   handleGoService = () => {
-    this.props.dispatch({
+    const {...propsData} = this.props;
+    propsData.dispatch({
       type: 'service/hideServiceInstance',
     });
   }
 
   handleGoServiceInstance = () => {
-    this.props.dispatch({
+    const {...propsData} = this.props;
+    propsData.dispatch({
       type: 'service/showServiceInstance',
     });
   }
 
   handleSelectServiceInstance = (serviceInstanceId, serviceInstanceInfo) => {
+    const {...propsData} = this.props;
     const { globalVariables: { duration } } = this.props;
-    this.props.dispatch({
+    propsData.dispatch({
       type: 'service/fetchServiceInstance',
       payload: { variables: { duration, serviceInstanceId }, serviceInstanceInfo },
     });
   }
 
   renderApp = () => {
-    const { getFieldDecorator } = this.props.form;
-    const { variables: { values, options, labels }, data } = this.props.service;
+    const {...propsData} = this.props;
+    const { getFieldDecorator } = propsData.form;
+    const { variables: { values, options, labels }, data } = propsData.service;
     return (
       <div>
         <Form layout="inline">
@@ -139,7 +147,7 @@
         </Form>
         <Panel
           variables={values}
-          globalVariables={this.props.globalVariables}
+          globalVariables={propsData.globalVariables}
           onChange={this.handleChange}
         >
           <Row gutter={0}>
@@ -168,7 +176,7 @@
                 <ServiceInstanceLitePanel
                   data={data}
                   serviceInstanceList={data.getServiceInstances}
-                  duration={this.props.duration}
+                  duration={propsData.duration}
                   onSelectServiceInstance={this.handleSelectServiceInstance}
                   onMoreServiceInstance={this.handleGoServiceInstance}
                 />
@@ -183,7 +191,7 @@
                 bodyStyle={{ padding: 5, height: 150}}
               >
                 <Line
-                  data={axisMY(this.props.duration, [{ title: 'p99', value: data.getP99}, { title: 'p95', value: data.getP95}
+                  data={axisMY(propsData.duration, [{ title: 'p99', value: data.getP99}, { title: 'p95', value: data.getP95}
                   , { title: 'p90', value: data.getP90}, { title: 'p75', value: data.getP75}, { title: 'p50', value: data.getP50}])}
                 />
               </Card>
@@ -212,7 +220,7 @@
                 <RankList
                   data={data.getSlowEndpoint}
                   renderValue={_ => `${_.value} ms`}
-                  onClick={(key, item) => redirect(this.props.history, '/monitor/endpoint', { key,
+                  onClick={(key, item) => redirect(propsData.history, '/monitor/endpoint', { key,
                     label: item.label,
                     serviceId: values.serviceId,
                     serviceName: labels.serviceId })}
@@ -226,7 +234,7 @@
   }
 
   render() {
-    const { service, duration } = this.props;
+    const { globalVariables, service, duration } = this.props;
     const { variables, data } = service;
     const { showServiceInstance, serviceInstanceInfo } = data;
     return (
@@ -244,7 +252,7 @@
             </Breadcrumb>
             <Panel
               variables={variables.values}
-              globalVariables={this.props.globalVariables}
+              globalVariables={globalVariables}
               onChange={this.handleChange}
             >
               <ServiceInstance data={data} duration={duration} />
diff --git a/src/routes/Topology/Topology.js b/src/routes/Topology/Topology.js
index 9b066df..a2c7948 100644
--- a/src/routes/Topology/Topology.js
+++ b/src/routes/Topology/Topology.js
@@ -155,20 +155,21 @@
   }
 
   renderActions = () => {
-    const { data: { appInfo } } = this.props.topology;
+    const {...propsData} = this.props;
+    const { data: { appInfo } } = propsData.topology;
     return [
-      <Icon type="appstore" onClick={() => redirect(this.props.history, '/monitor/service', { key: appInfo.id, label: appInfo.name })} />,
+      <Icon type="appstore" onClick={() => redirect(propsData.history, '/monitor/service', { key: appInfo.id, label: appInfo.name })} />,
       <Icon
         type="exception"
-        onClick={() => redirect(this.props.history, '/trace',
+        onClick={() => redirect(propsData.history, '/trace',
         { values: {
             serviceId: appInfo.id,
-            duration: { ...this.props.duration, input: this.props.globalVariables.duration },
+            duration: { ...propsData.duration, input: propsData.globalVariables.duration },
           },
           labels: { applicationId: appInfo.name },
         })}
       />,
-      appInfo.isAlarm ? <Icon type="bell" onClick={() => redirect(this.props.history, '/monitor/alarm')} /> : null,
+      appInfo.isAlarm ? <Icon type="bell" onClick={() => redirect(propsData.history, '/monitor/alarm')} /> : null,
     ];
   }
 
@@ -187,7 +188,8 @@
   }
 
   render() {
-    const { data, variables: { appRegExps, appFilters = [], latencyRange } } = this.props.topology;
+    const {...propsData} = this.props;
+    const { data, variables: { appRegExps, appFilters = [], latencyRange } } = propsData.topology;
     const { metrics, layout = 0 } = data;
     const { getGlobalTopology: topologData } = data;
     const content = (
@@ -198,7 +200,7 @@
       </div>
     );
     return (
-      <Panel globalVariables={this.props.globalVariables} onChange={this.handleChange}>
+      <Panel globalVariables={propsData.globalVariables} onChange={this.handleChange}>
         <Row gutter={8}>
           <Col {...{ ...colResponsiveProps, xl: 18, lg: 16 }}>
             <ChartCard
@@ -215,7 +217,7 @@
             >
               {topologData.nodes.length > 0 ? (
                 <AppTopology
-                  height={this.props.graphHeight}
+                  height={propsData.graphHeight}
                   elements={topologData}
                   metrics={metrics}
                   onSelectedApplication={this.handleSelectedApplication}
diff --git a/src/routes/Trace/Trace.js b/src/routes/Trace/Trace.js
index 6bfe06f..bbfdee8 100644
--- a/src/routes/Trace/Trace.js
+++ b/src/routes/Trace/Trace.js
@@ -29,13 +29,15 @@
 }))
 export default class Trace extends PureComponent {
   handleGoBack = () => {
-    this.props.dispatch({
+    const {...propsData} = this.props;
+    propsData.dispatch({
       type: 'trace/hideTimeline',
     });
   }
 
   render() {
     const { trace: { data: { showTimeline } } } = this.props;
+    const {...propsData} = this.props;
     return (
       <div>
         {showTimeline ? (
@@ -50,22 +52,22 @@
         <Row type="flex" justify="start">
           <Col span={showTimeline ? 0 : 24}>
             <TraceSearch
-              trace={this.props.trace}
-              duration={this.props.duration}
-              loading={this.props.loading}
-              globalVariables={this.props.globalVariables}
-              dispatch={this.props.dispatch}
-              zone={this.props.zone}
+              trace={propsData.trace}
+              duration={propsData.duration}
+              loading={propsData.loading}
+              globalVariables={propsData.globalVariables}
+              dispatch={propsData.dispatch}
+              zone={propsData.zone}
             />
           </Col>
           <Col span={showTimeline ? 24 : 0}>
             {showTimeline ? (
               <TraceTimeline
-                trace={this.props.trace}
-                duration={this.props.duration}
-                loading={this.props.loading}
-                globalVariables={this.props.globalVariables}
-                dispatch={this.props.dispatch}
+                trace={propsData.trace}
+                duration={propsData.duration}
+                loading={propsData.loading}
+                globalVariables={propsData.globalVariables}
+                dispatch={propsData.dispatch}
               />
             ) : null}
           </Col>
diff --git a/src/routes/Trace/TraceSearch.js b/src/routes/Trace/TraceSearch.js
index cb48a9b..59bbae7 100644
--- a/src/routes/Trace/TraceSearch.js
+++ b/src/routes/Trace/TraceSearch.js
@@ -53,9 +53,10 @@
 })
 export default class Trace extends PureComponent {
   componentDidMount() {
+    const {...propsData} = this.props;
     const { trace: { variables: { values } } } = this.props;
     const { duration } = values;
-    this.props.dispatch({
+    propsData.dispatch({
       type: 'trace/initOptions',
       payload: { variables: { duration: duration.input } },
     });
@@ -103,7 +104,8 @@
   }
 
   fetchData = (queryCondition, paging = initPaging) => {
-    this.props.dispatch({
+    const {...propsData} = this.props;
+    propsData.dispatch({
       type: 'trace/fetchData',
       payload: {
         variables: {
@@ -212,7 +214,8 @@
   }
 
   renderForm() {
-    const { getFieldDecorator } = this.props.form;
+    const {...propsData} = this.props;
+    const { getFieldDecorator } = propsData.form;
     const { trace: { variables: { options } }, zone } = this.props;
     return (
       <Form onSubmit={this.handleSearch} layout="vertical">
diff --git a/src/routes/User/Login.js b/src/routes/User/Login.js
index bd37e2a..e3aaed4 100644
--- a/src/routes/User/Login.js
+++ b/src/routes/User/Login.js
@@ -30,8 +30,9 @@
 }))
 export default class LoginPage extends Component {
   handleSubmit = (err, values) => {
+    const {...propsData} = this.props;
     if (!err) {
-      this.props.dispatch({
+      propsData.dispatch({
         type: 'login/login',
         payload: {
           ...values,
diff --git a/src/routes/User/Register.js b/src/routes/User/Register.js
index 87549fa..189abc0 100644
--- a/src/routes/User/Register.js
+++ b/src/routes/User/Register.js
@@ -53,9 +53,10 @@
   };
 
   componentWillReceiveProps(nextProps) {
-    const account = this.props.form.getFieldValue('mail');
+    const {...propsData} = this.props;
+    const account = propsData.form.getFieldValue('mail');
     if (nextProps.register.status === 'ok') {
-      this.props.dispatch(routerRedux.push({
+      propsData.dispatch(routerRedux.push({
         pathname: '/user/register-result',
         state: {
           account,
@@ -94,13 +95,15 @@
 
   handleSubmit = (e) => {
     e.preventDefault();
-    this.props.form.validateFields({ force: true }, (err, values) => {
+    const {...propsData} = this.props;
+    const {...stateData} = this.state;
+    propsData.form.validateFields({ force: true }, (err, values) => {
       if (!err) {
-        this.props.dispatch({
+        propsData.dispatch({
           type: 'register/submit',
           payload: {
             ...values,
-            prefix: this.state.prefix,
+            prefix: stateData.prefix,
           },
         });
       }
@@ -109,7 +112,8 @@
 
   handleConfirmBlur = (e) => {
     const { value } = e.target;
-    this.setState({ confirmDirty: this.state.confirmDirty || !!value });
+    const {...stateData} = this.state;
+    this.setState({ confirmDirty: stateData.confirmDirty || !!value });
   };
 
   checkConfirm = (rule, value, callback) => {
@@ -122,6 +126,7 @@
   };
 
   checkPassword = (rule, value, callback) => {
+    const {...stateData} = this.state;
     if (!value) {
       this.setState({
         help: '请输入密码!',
@@ -132,7 +137,7 @@
       this.setState({
         help: '',
       });
-      if (!this.state.visible) {
+      if (!stateData.visible) {
         this.setState({
           visible: !!value,
         });
@@ -141,7 +146,7 @@
         callback('error');
       } else {
         const { form } = this.props;
-        if (value && this.state.confirmDirty) {
+        if (value && stateData.confirmDirty) {
           form.validateFields(['confirm'], { force: true });
         }
         callback();
@@ -175,7 +180,9 @@
   render() {
     const { form, submitting } = this.props;
     const { getFieldDecorator } = form;
-    const { count, prefix } = this.state;
+    const { help, count, prefix } = this.state;
+    const { stateData } = this.state;
+    
     return (
       <div className={styles.main}>
         <h3>注册</h3>
@@ -194,7 +201,7 @@
               ],
             })(<Input size="large" placeholder="邮箱" />)}
           </FormItem>
-          <FormItem help={this.state.help}>
+          <FormItem help={help}>
             <Popover
               content={
                 <div style={{ padding: '4px 0' }}>
@@ -207,7 +214,7 @@
               }
               overlayStyle={{ width: 240 }}
               placement="right"
-              visible={this.state.visible}
+              visible={stateData.visible}
             >
               {getFieldDecorator('password', {
                 rules: [