如果不能使用setState,则使用什么



我试图通过从数据库中获取值并使用它来设置用户的状态。由于某些原因,状态不会自行更新,我尝试了等待和异步。如果这一个不能可靠地使其成为一个价值,还有什么其他选择。

我确实得到以下错误: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));

我建议你阅读一下Michael Chan的以下文章,这些文章将详细介绍设置状态

https://medium.learnreact.com/setstate-is-asynchronous-52ead919a3f0https://medium.learnreact.com/setstate-takes-a-callback-1f71ad5d2296https://medium.learnreact.com/setstate-takes-a-function-56eb940f84b6

async/awaitpromises的使用也有一些问题——看起来您在混合它们之间的语法。你要么用一个,要么用另一个,而不是两者都用。这篇文章详细介绍了它们之间的区别。

this.setState不返回promise,因此使用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,然后设置在componentWillUnmount中将其设置为false,并使用此变量进行检查组件的状态

这不是一个理想的解决方案,但它是最简单的,因为你真的应该取消你的承诺等,这样setState就永远不会被调用,因为承诺已经被取消。

相关内容

  • 没有找到相关文章

最新更新