From b72f927bb327e6754ba41d02a5844d79808c9714 Mon Sep 17 00:00:00 2001 From: WhatAKitty <104xuqiang@163.com> Date: Sat, 2 Dec 2017 17:06:43 +0800 Subject: [PATCH] Do safe state instead of setState #338 If you use this.setState in local component you should set @safeState and always use `this.props.setStateSafe` instead of native method `this.setState`, it will avoid `Can only update a mounted or mounting component` warning beacuse of setting state while component has already been unmounted. --- src/components/SafeState.js | 36 ++++++++++++++++++++++++++++++++ src/routes/Dashboard/Analysis.js | 12 ++++++----- 2 files changed, 43 insertions(+), 5 deletions(-) create mode 100644 src/components/SafeState.js diff --git a/src/components/SafeState.js b/src/components/SafeState.js new file mode 100644 index 0000000000..c3bb1a31c5 --- /dev/null +++ b/src/components/SafeState.js @@ -0,0 +1,36 @@ + +import React, { Component } from 'react'; + +export default () => (Comp) => { + return class SafeStateWrapper extends Component { + constructor(props) { + super(props); + this.mount = false; + + this.setStateSafe = this.setStateSafe.bind(this); + } + + componentDidMount() { + this.mount = true; + } + + componentWillUnmount() { + this.mount = false; + } + + setStateSafe(...params) { + return this.mount && this.child.setState(...params); + } + + render() { + return ( + { this.child = ref; }} + setStateSafe={this.setStateSafe} + /> + ); + } + }; +}; diff --git a/src/routes/Dashboard/Analysis.js b/src/routes/Dashboard/Analysis.js index 3f0b3765b2..b7fb5a8caf 100644 --- a/src/routes/Dashboard/Analysis.js +++ b/src/routes/Dashboard/Analysis.js @@ -8,6 +8,7 @@ import { import Trend from '../../components/Trend'; import NumberInfo from '../../components/NumberInfo'; import { getTimeDistance } from '../../utils/utils'; +import safeState from '../../components/SafeState'; import styles from './Analysis.less'; @@ -25,6 +26,7 @@ for (let i = 0; i < 7; i += 1) { @connect(state => ({ chart: state.chart, })) +@safeState() export default class Analysis extends Component { state = { loading: true, @@ -36,7 +38,7 @@ export default class Analysis extends Component { componentDidMount() { this.props.dispatch({ type: 'chart/fetch', - }).then(() => this.setState({ loading: false })); + }).then(() => this.props.setStateSafe({ loading: false })); } componentWillUnmount() { @@ -47,19 +49,19 @@ export default class Analysis extends Component { } handleChangeSalesType = (e) => { - this.setState({ + this.props.setStateSafe({ salesType: e.target.value, }); } handleTabChange = (key) => { - this.setState({ + this.props.setStateSafe({ currentTabKey: key, }); } handleRangePickerChange = (rangePickerValue) => { - this.setState({ + this.props.setStateSafe({ rangePickerValue, }); @@ -69,7 +71,7 @@ export default class Analysis extends Component { } selectDate = (type) => { - this.setState({ + this.props.setStateSafe({ rangePickerValue: getTimeDistance(type), });