【问题标题】:Previous screen called when navigating to new one in React Native在 React Native 中导航到新屏幕时调用的上一个屏幕
【发布时间】:2021-05-16 23:43:01
【问题描述】:

我遇到了与here 描述的完全相同的问题。使用选项卡或抽屉在屏幕之间导航时,每个屏幕都会重新加载,从而导致我的应用出现问题。

我已尝试遵循线程中给出的一些建议,但我无法将其应用于我的代码。例如:

对我来说,解决方案是将导航器作为屏幕组件的子级嵌套,而不是将导航器插入到组件属性中。

将其包装在文件的顶层并将其分配给一个变量,然后在组件中使用该变量。

我的抽屉由 4 个指向 4 个屏幕(主页、历史记录、组、设置)的快捷方式组成。前三个也可以在主屏幕的底部选项卡中找到。

这是我的代码: Navigation.js

import React from "react";
import { TouchableOpacity } from "react-native";
import { NavigationContainer} from "@react-navigation/native";
import { createStackNavigator } from "@react-navigation/stack";
import { createBottomTabNavigator } from "@react-navigation/bottom-tabs";
import { createDrawerNavigator } from "@react-navigation/drawer";

import { Entypo } from "@expo/vector-icons";

import Settings from "../screens/Settings";
import Loading from "../screens/Loading";
import AddGroup from "../screens/AddGroup";
import GroupList from "../screens/GroupList";

import Home from "../screens/Home";
import Groups from "../screens/Groups";
import History from "../screens/History";

const HomeStack = createStackNavigator();
const HomeStackScreen = ({ route }) => (
  <HomeStack.Navigator}>
    <HomeStack.Screen
      name={route.name}
      component={Home}
    />
  </HomeStack.Navigator>
);

const HistoryStack = createStackNavigator();
const HistoryStackScreen = ({ route }) => (
  <HistoryStack.Navigator>
    <HistoryStack.Screen
      name={route.name}
      component={History}
    />
  </HistoryStack.Navigator>
);

const GroupsStack = createStackNavigator();
const GroupsStackScreen = ({ route }) => (
  <GroupsStack.Navigator>
    <GroupsStack.Screen
      name={route.name}
      component={Groups}
    />
  </GroupsStack.Navigator>
);

const AppTabs = createBottomTabNavigator();
const bottomTabsScreen = ({ route }) => (
  <AppTabs.Navigator>
    <AppTabs.Screen
      name="Home"
      component={HomeStackScreen}
    />
    <AppTabs.Screen
      name="History"
      component={HistoryStackScreen}
    />

    <AppTabs.Screen
      name="Groups"
      component={GroupsStackScreen}
    />
  </AppTabs.Navigator>
);

const AppDrawer = createDrawerNavigator();
const AppDrawerScreen = ({ navigation }) => (
  <AppDrawer.Navigator>
    <AppDrawer.Screen name="Home" component={bottomTabsScreen} />

    <AppDrawer.Screen name="History" component={HistoryStackScreen} />

    <AppDrawer.Screen name="Groups" component={GroupsStackScreen} />

    <AppDrawer.Screen name="Settings" component={Settings} />
  </AppDrawer.Navigator>
);

const RootStack = createStackNavigator();
const RootStackScreen = () => {
  const [isLoading, setIsLoading] = React.useState(true);

  React.useEffect(() => {
    setTimeout(() => {
      setIsLoading(!isLoading);
    }, 500);
  }, []);

  return (
    <RootStack.Navigator mode="modal">
      {isLoading ? (
        <RootStack.Screen name="Loading" component={Loading} />
      ) : (
        <RootStack.Screen
          name="AppDrawerScreen"
          component={AppDrawerScreen}
        />
      )}
      <RootStack.Screen
        name="AddGroup"
        component={AddGroup}
        options={modalOptionStyle}
      />

      <RootStack.Screen
        name="GroupList"
        component={GroupList}
        options={({ navigation }) => ({
          headerTitle: "Select an existing group",
        })}
      />
    </RootStack.Navigator>
  );
};

export default () => {
  return (
    <NavigationContainer>
      <RootStackScreen />
    </NavigationContainer>
  );
};

index.js:

import React from "react";
import Navigation from "./config/Navigation";
import { ConversionContextProvider } from "./util/ConversionContext";

export default () => (
  <ConversionContextProvider>
    <Navigation />
  </ConversionContextProvider>
);

遵循 x00 建议后的最终工作代码:

useEffect(() => {
  if (isFocusedGroups) setLoading(true);
  const unsubscribe = navigation.addListener("focus", () => {
    loadFlatlist("groups")
      .then()
      .catch((error) => console.error(error))
      .finally(() => {
        setLoading(false);
      });
  });
  return unsubscribe;
}, [navigation, isFocusedGroups]);

【问题讨论】:

  • 您的代码有错误。一方面:modalOptionStyle 未定义。可能没关系,但掩盖了你的问题。 AppDrawerScreen 中的 navigation 道具也是如此,您实际上并未使用。等等。请消除噪音并制作一个最小可重现的例子(你很有可能在这个过程中自己解决你的问题)。此外,您应该显示一些屏幕的代码和导航方式。内联函数options={({ navigation }) =&gt; ({ headerTitle: "Select an existing group" })} 也可能导致一些重新渲染,但可能仅适用于GroupList。无论如何,我们需要更多代码
  • 我创建了一个 repro here,我将在今天晚些时候尝试用最少的代码清理它。在 History 和 Groups 选项卡之间切换时,您可以在控制台中看到 "LOADING FLATLIST (loadFlatlist) FOR: savedRuns" 每次执行。我认为这是问题的根本原因。

标签: react-native react-navigation


【解决方案1】:

形成你的回购:

...
import { useIsFocused } from "@react-navigation/native";
...
const History = ({ navigation }) => {
  ...
  const isFocusedHistory = useIsFocused();
  ...
  useEffect(() => {
    ...
    loadFlatlist("savedRuns")
    ...
  }, [isFocusedHistory]);
  ...
}

每次用户打开关闭标签isFocusedHistory都会发生变化,因此相应的组件会重新渲染并触发效果。

尚未阅读您编写的整个应用程序,也没有尝试了解所需的行为是什么,因此无法准确说明您需要如何更改它。但这是你问题的根本原因。

您可能应该放弃在选项卡开关上检索数据的想法。无论如何,这不是一个好主意。

【讨论】:

  • 谢谢,我删除了它,但问题是当我移动选项卡时选项卡中的数据没有刷新。为什么这不是一个好主意?如果用户保存运行,然后转到History,然后返回Home 保存另一个运行,我希望第二次运行显示在History 的平面列表中,如果用户导航到那里(即调用@987654326 @ 再次)。我的印象是useIsFocused 会帮助我做到这一点。
  • 您可以使用某种存储(Redux、MobX 等),您可以将数据作为 props 或在上下文中传递。但是,如果您想在选项卡切换上请求数据,则只会在重新渲染时伴随发生。 useEffect 不会神奇地在后台运行(除非你将 setInterval 放在那里)
  • 好吧,我仍然不知道想要的行为。但是您只能在显示选项卡时运行useEffect(而不是在隐藏选项卡时)。为此,您可以简单地将if(isFocusedHistory) 放在useEffect
  • 谢谢,我终于设法解决了。在我原来的问题中添加了工作示例
猜你喜欢
  • 2022-01-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-01-25
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多