【发布时间】:2017-12-14 07:44:36
【问题描述】:
我最近在 React 中遇到了这个错误:
warning.js:36 警告:setState(...): Can only update amounted or 安装组件。这通常意味着您在一个 未安装的组件。这是一个无操作。请检查代码 BillingDetails 组件。
挖掘后我发现这是因为我在未安装的组件中执行setState这样的:
componentWillMount() {
this.fetchBillings(this.props.userType);
}
componentWillReceiveProps({ userType }) {
if (this.props.userType !== userType) {
this.fetchBillings(userType);
}
}
fetchBillings = userType => {
switch (userType) {
case USER_TYPE.BRAND:
this.props.fetchBrandBillings()
.then(() => this.setState({ isLoading: false }));
return;
default:
}
};
fetchBillings 是一个 redux-axios action creator,它返回一个承诺
export const fetchBrandBillings = () => ({
type: FETCH_BRAND_BILLINGS,
payload: {
request: {
method: 'GET',
url: Endpoints.FETCH_BRAND_BILLINGS,
},
},
});
问题是当用户在站点快速移动时,组件可能会在 promise 解决时被卸载。
我发现项目周围的很多地方都在做这样的事情:
componentWillMount() {
const { router, getOrder, params } = this.props;
getOrder(params.orderId).then(action => {
if (action.type.endsWith('FAILURE')) {
router.push(`/dashboard/campaign/${params.campaignId}`);
}
})
}
现在我开始认为在组件中使用 Promise 可能是反模式,因为组件可以随时卸载...
【问题讨论】:
-
我认为
redux使用promise 来改变状态,然后使用react-redux的connect将组件与状态挂钩更习惯。然后库负责确保您不会不恰当地改变组件。 -
promise 没问题,但是你必须在 componentDidMount 和 componentWillReceiveProps 中做,而不是在渲染之前或渲染期间
-
@AnisSmail 在组件中有
isLoading标志似乎是个好地方,特别是如果您需要渲染几个相同的组件并且每个组件都必须执行 api 请求。无论如何isLoading只是其中一种情况,例如,有时您想更改路线。 -
好的,我明白了。也许看看这个答案:stackoverflow.com/a/37771337/4099279,我不知道是否有更干净的方法来“停止” axios 请求
-
@Tomasz,看看这个:github.com/mzabriskie/axios#cancellation 可以取消正在进行的 axios 请求。我不知道 redux-axios 是如何处理它的
标签: reactjs redux redux-thunk