理解反应本机导航

Understanding react-native navigation

我想知道当您单击 gobacknavigation.pop()

时,react 是否会从其内存中删除组件

在这种情况下我使用 navigation.Push 而不是 navigation.navigate

内存和性能会不会有问题?

我需要做一些特别的事情来清除那些吗?

react-native-navigation lifecycle 中,如果您离开在 Stack 上按下的屏幕,屏幕将保持安装状态。

Consider a native stack navigator with screens A and B. After navigating to A, its componentDidMount is called. When pushing B, its componentDidMount is also called, but A remains mounted on the stack and its componentWillUnmount is therefore not called.

另一方面。

When going back from B to A, componentWillUnmount of B is called, but componentDidMount of A is not because A remained mounted the whole time.

我们可以通过创建一个简单的 StackNavigator 和文档中的两个屏幕来测试它。使用空依赖项数组创建 useEffect 并记录如下内容。

import React, {useState, useEffect} from 'react';
import { Button, View, Text } from 'react-native';
import { NavigationContainer } from '@react-navigation/native';
import { createNativeStackNavigator } from '@react-navigation/native-stack';

function HomeScreen({ navigation, route }) {

  return (
    <View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
      <Text>Home Screen</Text>
      <Button
        title="Go to ScreenA"
        onPress={() => navigation.navigate('ScreenA')}
      />
    </View>
  );
}

function ScreenA({ navigation, route }) {

  useEffect(() => {
    console.log("Screen A")
  }, [])

  return (
    <View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
      <Text>Details Screen</Text>
      <Button
        title="Go to ScreenB"
        onPress={() => navigation.navigate('ScreenB')}
      />
    </View>
  );
}

function ScreenB({ navigation, route }) {
  useEffect(() => {
    console.log("Screen B")
  },[])

  return (
    <View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
      <Text>Details Screen</Text>
      <Button
        title="Go to ScreenA"
        onPress={() => navigation.navigate('ScreenA')}
      />
    </View>
  );
}

const Stack = createNativeStackNavigator();

function App() {
  return (
    <NavigationContainer>
      <Stack.Navigator initialRouteName="Home">
        <Stack.Screen name="Home" component={HomeScreen} />
        <Stack.Screen name="ScreenA" component={ScreenA} />
        <Stack.Screen name="ScreenB" component={ScreenB} />
      </Stack.Navigator>
    </NavigationContainer>
  );
}

export default App;

考虑以下导航路线:

  • ScreenA -> ScreenB -> ScreenA -> ScreenB

我们会注意到以下日志消息:

  • ScreenAScreenBScreenB

这是因为 ScreenA 保持安装状态ScreenB 被卸载并再次安装

现在,如果我们 push 一个屏幕会怎样?我们也可以使用相同的示例进行测试,但 pushing ScreenB in ScreenB itself 如下。

function ScreenB({ navigation, route }) {
  useEffect(() => {
    console.log("Screen B")
  },[])

  return (
    <View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
      <Text>Details Screen</Text>
      <Button
        title="Push to ScreenB"
        onPress={() => navigation.push('ScreenB')}
      />
    </View>
  );
}

我们会注意到在每个 push 上安装了一个新的 ScreenB

如果我们使用 navigation.pop 会怎样?正在 poped 的屏幕将被卸载,如果我们出于与上述相同的原因使用 goBack,也会发生同样的情况。

Performance-wise,使用navigation.pop()navigation.goBack()将在卸载时释放我们调用这些函数的屏幕内存。

另一方面,在 Stack 上不断 pushing the same screen 并不是一个好主意。

我还会考虑 useEffect 中的代码。如果是 API 调用,那么我们通常希望它只被调用一次。从这个角度来看,希望屏幕在我们进入后保持安装状态。

总而言之,goBackpop 将卸载我们调用这些函数的屏幕。 React native 会释放屏幕占用的内存(以状态、变量等形式)。您不必做任何特别的事情。

我主要使用上面的代码做了一个little snack