我试图通过从数据库中获取值然后使用它来设置用户状态。由于某种原因,状态无法自我更新,因此我尝试了await和async。如果不能可靠地使它成为一个值,还有什么其他选择。
我确实收到以下错误:Warning: Can't call setState (or forceUpdate) on an unmounted component. This is a no-op, but it indicates a memory leak in your application. To fix, cancel all subscriptions and asynchronous tasks in the componentWillUnmount method.
- node_modules/fbjs/lib/warning.js:33:20 in printWarning
- node_modules/fbjs/lib/warning.js:57:25 in warning
- node_modules/react-native/Libraries/Renderer/ReactNativeRenderer-dev.js:12196:6 in warnAboutUpdateOnUnmounted
- node_modules/react-native/Libraries/Renderer/ReactNativeRenderer-dev.js:13273:41 in scheduleWorkImpl
- node_modules/react-native/Libraries/Renderer/ReactNativeRenderer-dev.js:6224:19 in enqueueSetState
- node_modules/react/cjs/react.development.js:242:31 in setState
* null:null in componentWillMount$
- node_modules/regenerator-runtime/runtime.js:62:44 in tryCatch
- node_modules/regenerator-runtime/runtime.js:296:30 in invoke
- ... 13 more stack frames from framework internals
constructor() {
super();
this.state = {
userPhoneNumber: "",
};
}
async componentWillMount() {
await firebase.database().ref('/Users/' + firebase.auth().currentUser.uid).on('value', async snap => {
if (snap) {
await this._setPhone(snap.val())
} else {
this.props.navigation.navigate('Phone')
}
});
console.log(this.state.userPhoneNumber);
}
_setPhone = (snap) => {
const val = parseInt(snap, 10);
this.setState({
userPhoneNumber: val
})
};
答案 0 :(得分:3)
如果您确定收到的是ccc
的正确值。那么您遇到的问题是snap
是异步的。这意味着状态设置需要花费时间。
不幸的是,他们用这种方式检查状态以查看是否设置了错误的值。
您应该在setState
函数中使用回调,这样您的setState
会变成:
setState
我建议您阅读Michael Chan的以下文章,其中更详细地介绍了设置状态
https://medium.learnreact.com/setstate-is-asynchronous-52ead919a3f0 https://medium.learnreact.com/setstate-takes-a-callback-1f71ad5d2296 https://medium.learnreact.com/setstate-takes-a-function-56eb940f84b6
使用this.setState({userPhoneNumber: val}. () => console.log(this.state.userPhoneNumber));
和async/await
时还存在一些问题,似乎您在混合使用它们之间的语法。您可以使用其中之一,而不能同时使用两者。 article详细介绍了它们之间的区别。
promises
不会返回承诺,因此使用this.setState
不会执行任何操作。
这就是我重构您的代码的方式:
await this.setState
在卸载组件后,您必须正在调用componentDidMount() { // componentWillMount is deprecated
// you are using a promise to access firebase so you shouldn't be using `async/await`
firebase.database().ref('/Users/' + firebase.auth().currentUser.uid).on('value', snap => {
if (snap) {
this._setPhone(snap.val()) // remove the await as it is not doing anything
} else {
this.props.navigation.navigate('Phone')
}
});
}
_setPhone = (snap) => {
const val = parseInt(snap, 10);
this.setState({ userPhoneNumber: val}, () => console.log(this.state.userPhoneNumber)) // include the callback to check the value of state
};
。在调用setState之前,需要检查以确保已安装组件。
一种方法是通过具有一个布尔标志来监视何时安装组件。
setState
设置状态后,您可以执行以下操作
componentDidMount () {
this._isMounted = true;
}
componentWillMount () {
this._isMounted = false;
}
您可以在这里https://reactjs.org/blog/2015/12/16/ismounted-antipattern.html
中查看更多信息只需在componentDidMount中将_isMounted属性设置为true并设置 在componentWillUnmount中将其设置为false,并使用此变量进行检查 您组件的状态
这不是理想的解决方案,但它是最简单的解决方案,因为您实际上应该取消诺言等,因此if (this._isMounted) {
this.setState({key: value});
}
永远不会因为诺言被取消而被调用。