这个错误是什么问题呢This usually means you called setState() on an unmounted component

#1

这个错误是哪里有问题呢,大家帮我看看吧
Warning: setState(…): Can only update a mounted or mounting component. This usually means you called setState() on an unmounted component. This is a no-op. Please check the code for the CustomerBox component.

export default class CustomerBox extends Component{
	constructor(){
		super();
		this.state = {
			url: rootPath + "/mobile/crm/customer/list?callback=?",
			todolist: null,
			alltodolist: [],
			loading: true,
			error: null,
			data: null,
			generatedCount: 1,
		};
	}
	componentWillMount(){
		this.repoList = $.getJSON(this.state.url).then(
			value => {
				if(localStorage.getItem('customerList') == '' || localStorage.getItem('customerList') == null){
					this.setState({loading: false, data: value, todolist: value.data.customerList});
					localStorage.setItem('customerList', JSON.stringify(value));
				}else{
					this.setState({loading: false, data: JSON.parse(localStorage.getItem('customerList')), todolist: JSON.parse(localStorage.getItem('customerList')).data.customerList});
				}
			},
			error => this.setState({loading: false, error: error})
		);
	}
	render() {
		return (
			<div className="AppBox">
				<div className="box">
					<CustomerHeader />
					<div className="mui-content edit-content content" id="content" style={{"paddingTop": immersed,"height": immersed + 45 + "px"}}>
						
					</div>
				</div>
			</div>
		)
	}
}
#2

异步获取到数据,执行setState的时候,这个组件已经销毁了

#3

先把代码排版好,这样看的太累了

这个问题就是你在 componentWillMount 的时候使用了 setState(),然而这个时候组件还没有 mount

所以建议你将数据请求的逻辑放到 componentDidMount 方法中

#4

恰恰相反,componentWillMount是可以setState,而componentDidMount是不建议setState的

#5

额,看来我一直以来的理解有问题啊

虽然会触发第二次 render ,但是如果在 willMount 中请求数据,这个过程中页面岂不是一片空白?

#6

不会空白的,异步处理的数据在componentWillMount和componentDidMount在第一次请求的时候,行为是差不多的,都是等拿到数据,二次render,只是第二次请求时数据有缓存,setState的时间很短,就可以直接渲染了。

#7

嗯,照你这样说来异步请求的话放在两个方法中没有区别呀?

https://facebook.github.io/react/tips/initial-ajax.html 因为之前也是看官方的文档是这样做的

还有这个 https://facebook.github.io/react/docs/component-specs.html#mounting-componentwillmount

#8

我用abort()这个方法来取消请求,但是为什么在componentWillUnmount取不到变量呢

Uncaught TypeError: this.serverRequest.abort is not a function

componentDidMount(){
		if(localStorage.getItem('customerList') == '' || localStorage.getItem('customerList') == null){
			this.serverRequest = $.getJSON(this.state.url).then(
				value => {
					this.setState({loading: false, data: value, todolist: value.data.customerList});
					localStorage.setItem('customerList', JSON.stringify(value));
				},
				error => this.setState({loading: false, error: error})
			)
		}else{
			this.setState({loading: false, data: JSON.parse(localStorage.getItem('customerList')), todolist: JSON.parse(localStorage.getItem('customerList')).data.customerList});
		}
	}
	componentWillUnmount() {  
	    this.serverRequest.abort();  
	}
#9

有缓存的话,就有区别了,有缓存的情况下,会在下一次render之前,执行了回调的setState,不会二次render。

#10

先看看this是什么

#11
componentWillMount () {
  this._isMounted = true
  fetch('xxxx').then(res => {
    if (this._isMounted) this.setState({ xxxx: res })
  })
}

componentWillUnmount () {
  this._isMounted = false
}
1 Like
#12

谢谢,问题解决了

#13

怎么解决的?

#14

解决了麻烦贴出解决方案, 方便后来人…

#15

使用则个方法解决了 赞

#16

并不是没有卸载,而是执行一个异步方法的回掉函数时,对应的组件已经卸载掉了,所以会出现上述提示。
解决的办法是在回调函数中使用this.isMounted检查组件是否仍处于加载状态,再使用 setState 进行操作。

#17

this.isMounted已经不建议使用了。

#18

componentWIllMount里是可以,setState的,只是页面只渲染一次

#19

这个高阶组件可以比较优雅的解决这个问题, https://github.com/iShawnWang/withUnmounted