如何在 React Native 中清理 class 组件中的状态?

How to clean up state in class component in React Native?

我是 React Native 的新手,正在努力清理屏幕状态。

比如屏幕 A 有一些状态 --> 屏幕 B,回到屏幕 A,旧状态很清楚。我正在使用 React Navigation V5

我想做的是:

  1. MainMap.js导航到最后一屏TripsListScreen.js后(整个过程是一个Stack of 4 screens,嵌套在一个Drawer中),我得到了所有存储在Redux的store中的数据,并且在 TripsListScreen.
  2. 中显示
  3. 问题是当我在 TripsListScreen 按下 add 按钮在 MainMap.js 返回时,它并没有像我预期的那样清理每个状态。

这是 MainMap.js 的状态:

const initialState = {
    hasMapPermission: false,
    _userLocationDisplayed: null,
    userLatitude: 0,
    userLongitude: 0,
    initial_UserLatitude: 0,
    initial_UserLongitude: 0,
    userLocationAddress: '',

    destination: [],
    destinationName: [],
    destinationAddress: [],
    destinationCoords: [],
    destinationImageUri: [],

    numOfInput:[0,1],
    counter: 1,
    wayPoints: [],
    markers: [],
}

class MainMap extends React.Component{

    constructor(props){
        super(props);

        this.state = initialState;


    };


    componentDidMount(){
        console.log('Hello',this.props)
        if(this.props.route.params === true){
            this.setState(initialState)
        }
        this._requestUserLocation();
    };

基本上,我尝试将布尔参数从 TripsListScreen 传递到 MainMap,如果参数为真,我会将所有状态设置回开头。但是,它没有按预期工作。

这里是TripsListScreen:

//...
<Layout style={styles.bottom}>
      <TouchableOpacity onPress={() => props.navigation.navigate('PlanningProcess', {
            screen: 'MainMapScreen',
            params: {doAddPlace: true}
      })} style={styles.createTrip}>
          <Layout style={styles.button} >
               <Icon name='add' size={35} />
          </Layout>
      </TouchableOpacity>
</Layout>
//...

这是导航

  1. StackNavigators:
const Stack = createStackNavigator();

const StackNavigator = (props) => {
    return(
        <Stack.Navigator screenOptions={{headerShown: false}}>
            <Stack.Screen name='MainMapScreen' component={MainMap} />
            <Stack.Screen name='TripDescription' component={TripDescription} />
            <Stack.Screen name='TripsListDetailScreen' component={TripsListDetailScreen} />
            <Stack.Screen
                name='TripsListScreen' 
                component={TripsListScreen} 
                options={{
                    headerLeft: () => (<Icon style={{marginHorizontal: 30, marginTop: 30}} color='white' name='menu' size={30} onPress={() => props.navigation.dispatch(DrawerActions.openDrawer())}/>),
                    title:'Something'
                    }}
            />
        </Stack.Navigator>
    );
};
export default StackNavigator;
  1. 主要Navigators:
const Navigator = () => {

    return(
        <NavigationContainer>
            <Drawer.Navigator
                statusBarAnimation='slide'
                drawerContent={props => 
                    <DrawerContent {...props} />}>
                <Drawer.Screen name='Welcome' component={WelcomeStackScreen}  />
                <Drawer.Screen name='TripsListScreen' component={TripsListScreen} />
                <Drawer.Screen name='PlanningProcess' component={StackNavigators} />
            </Drawer.Navigator>

        </NavigationContainer>
    );
};


export default Navigator;

这是 MainMap 呈现的内容:

这是我预期的,当从 TripsListScreen 导航时(创建新行程):

请帮忙!!!

在 StackNavigator 中,当您在屏幕顶部打开新屏幕时,屏幕不会卸载。因此,如果您从 A 转到 B,然后从 B 转到 C,A 和 B 都将保持挂载状态。如果您从 C 返回到 B,C 将卸载。这就像数组上的 pushpop 方法。当您返回 MainMap 时,componentDidMount 不会被调用,因为它不会首先卸载。这里解释一下Navigation Lifecycle

当您使用 Redux 并说所有数据都存储在 Redux 存储中时,让您的 MainMap 组件仅从存储中的数据呈现,而不是从自己的状态中呈现。然后,您可以通过调度操作从 TripsListScreen 操纵这些数据。最简单的方法是创建类似 RESET_MAIN_MAP 的操作,它将重置 MainMap 屏幕

的那部分状态

MainMap.js 中的 ComponentDidMount 不会被触发,因为屏幕已经安装。请看这个

方法 ComponentDidMount() 仅在第一次安装组件时触发,当您导航到新屏幕时,前一个屏幕仍安装在堆栈中。

如果您想在每次组件获得焦点时重新初始化您的状态,您可以在导航焦点上设置一个侦听器。

像这样,

const unsubscribe = navigation.addListener('willFocus', () => {
      // Do something 
      // re-initialise the state
});