React-navigation 文档explicitly described this case:
考虑一个带有屏幕 A 和 B 的堆栈导航器。导航到
A、它的componentDidMount被调用。当推 B 时,它的
componentDidMount 也被调用,但 A 仍然安装在堆栈上
因此它的 componentWillUnmount 不会被调用。
从B回到A时,B的componentWillUnmount被调用,但是
A 的 componentDidMount 不是因为 A 保持整个挂载
时间。
现在有 3 个解决方案:
订阅生命周期事件
...
React Navigation 向订阅的屏幕组件发出事件
他们。您可以订阅四种不同的事件:
willFocus、willBlur、didFocus 和 didBlur。在
API 参考。
withNavigationFocus 可能涵盖您的许多用例
高阶组件、<NavigationEvents /> 组件或
useFocusState钩子。
-
withNavigationFocus
higher-order-component
-
<NavigationEvents />
component
-
useFocusState hook(已弃用)
withNavigationFocus
高阶分量
import React from 'react';
import { Text } from 'react-native';
import { withNavigationFocus } from 'react-navigation';
class FocusStateLabel extends React.Component {
render() {
return <Text>{this.props.isFocused ? 'Focused' : 'Not focused'}</Text>;
}
}
// withNavigationFocus returns a component that wraps FocusStateLabel and passes
// in the navigation prop
export default withNavigationFocus(FocusStateLabel);
<NavigationEvents /> 组件
import React from 'react';
import { View } from 'react-native';
import { NavigationEvents } from 'react-navigation';
const MyScreen = () => (
<View>
<NavigationEvents
onWillFocus={payload => console.log('will focus', payload)}
onDidFocus={payload => console.log('did focus', payload)}
onWillBlur={payload => console.log('will blur', payload)}
onDidBlur={payload => console.log('did blur', payload)}
/>
{/*
Your view code
*/}
</View>
);
export default MyScreen;
useFocusState 挂钩
首先安装库yarn add react-navigation-hooks
import { useNavigation, useNavigationParam, ... } from 'react-navigation-hooks'
function MyScreen() { const focusState = useFocusState(); return <Text>{focusState.isFocused ? 'Focused' : 'Not Focused'}</Text>; }
这是我的个人解决方案,仅在从您的 API 获取数据时才使用 onDidFocus() 和 onWillFocus() 呈现:
import React, { PureComponent } from "react";
import { View } from "react-native";
import { NavigationEvents } from "react-navigation";
class MyScreen extends PureComponent {
state = {
loading: true
};
componentDidMount() {
this._doApiCall();
}
_doApiCall = () => {
myApiCall().then(() => {
/* Do whatever you need */
}).finally(() => this.setState({loading: false}));
};
render() {
return (
<View>
<NavigationEvents
onDidFocus={this._doApiCall}
onWillFocus={() => this.setState({loading: true})}
/>
{!this.state.loading && /*
Your view code
*/}
</View>
);
}
}
export default MyScreen;