我试图通过让从我的数据库的值,然后用它来设置用户的状态。出于某种原因,状态不更新本身我试图等待和异步。如果这个人能不可靠,使这是一个值存在什么其他的选择。
我得到了以下错误: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
})
};
如果您确信您收到的snap
正确的值。然后,你有问题是setState
是异步的。这意味着它需要时间的状态进行设置。
不幸的是他们的方式要检查你的状态,看是否已经被设置的值是错误的。
你应该在setState
功能使用回调,所以你setState
将成为:
this.setState({userPhoneNumber: val}. () => console.log(this.state.userPhoneNumber));
我会建议采取由迈克尔·陈是进入更详细了解时状态的以下文章的读
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
也有与您使用async/await
的几个问题,并promises
它看起来像你混合它们之间的语法。你要么使用一个或另一个,而不是两个。这article进入关于它们之间的差异的细节。
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;
}
当你设置你的状态,你可以做这样的事情
if (this._isMounted) {
this.setState({key: value});
}
你可以看到更多关于它这里https://reactjs.org/blog/2015/12/16/ismounted-antipattern.html
在componentDidMount一个_isMounted属性正好被设置为true和将其设置为false componentWillUnmount,并使用这个变量来检查你的组件的状态
这难道不是一种理想的解决方案,但它是最简单的,因为你真的应该取消你的承诺等,这样的承诺已经取消了setState
永远不会被调用。