理解反应本机导航
Understanding react-native navigation
我想知道当您单击 goback
或 navigation.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
我们会注意到以下日志消息:
ScreenA
、ScreenB
、ScreenB
这是因为 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 调用,那么我们通常希望它只被调用一次。从这个角度来看,希望屏幕在我们进入后保持安装状态。
总而言之,goBack
和 pop
将卸载我们调用这些函数的屏幕。 React native 会释放屏幕占用的内存(以状态、变量等形式)。您不必做任何特别的事情。
我主要使用上面的代码做了一个little snack。
我想知道当您单击 goback
或 navigation.pop()
在这种情况下我使用 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
我们会注意到以下日志消息:
ScreenA
、ScreenB
、ScreenB
这是因为 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 调用,那么我们通常希望它只被调用一次。从这个角度来看,希望屏幕在我们进入后保持安装状态。
总而言之,goBack
和 pop
将卸载我们调用这些函数的屏幕。 React native 会释放屏幕占用的内存(以状态、变量等形式)。您不必做任何特别的事情。
我主要使用上面的代码做了一个little snack。