javascript - 切换屏幕时 useEffect 不起作用

标签 javascript reactjs react-native react-hooks

嗨,我对react-native还是个新手,一直在尝试创建一个应用程序。 我的困惑是,我不知道为什么在通过react-navigation-bottom-tab切换屏幕时useEffect不起作用。 下面是我的 HomeScreen.js,我在其中编写了 useEffect 从 Firestore 获取所有数据。 正如你所看到的,我写了两个 useEffects 因为我认为它会起作用。 当我从 ProfileScreen 切换到主页时,第一个被认为是获取数据。

import {
  View,
  FlatList,
  StyleSheet,
} from "react-native";
import { RideCard } from "./RideCard";
import { OneTouchFilter } from "./OneTouchFilter";
import { useFirestoreContext } from "../../contexts/FirestoreContext";
import { useEffect } from "react";

export const HomeScreen = ({ navigation }) => {
  console.log("HomeScreen.js useEffect");
  const { selectedBoardType, cityFromText, cityToText, fetchRides, rides } =
    useFirestoreContext();

  useEffect(() => {
    fetchRides();
  }, []);
  
  useEffect(() => {
    fetchRides();
  }, [selectedBoardType, cityFromText, cityToText]);

  return (
    <View style={styles.inner}>
      <OneTouchFilter />
      <FlatList
        data={rides}
        renderItem={(itemData) => (
          <RideCard
            ride={itemData.item}
            index={itemData.index}
            id={itemData.item.id}
            numOfRides={rides.length}
          />
        )}
      />
    </View>
  );
};

App.js

这是放置react-navigation-bottom-tab的文件。

import React, { useContext } from "react";
import { StyleSheet } from "react-native";
import { NavigationContainer, DefaultTheme } from "@react-navigation/native";
import { createStackNavigator } from "@react-navigation/stack";
import { createBottomTabNavigator } from "@react-navigation/bottom-tabs";
import { HomeScreen } from "./screens/Home/HomeScreen";
import { PostScreen } from "./screens/Post/PostScreen";
import { ProfileScreen } from "./screens/Profile/ProfileScreen";
import Ionicons from "react-native-vector-icons/Ionicons";
import { NativeBaseProvider } from "native-base";
// create another file for contexts Provider
import { AuthContextProvider } from "./contexts/AuthContext";
import { FirestoreContextProvider } from "./contexts/FirestoreContext";
import { FormContextProvider } from "./contexts/FormContext";
const MyTheme = {
  ...DefaultTheme,
  colors: {
    ...DefaultTheme.colors,
    background: "white",
  },
};

export default function App() {
  const Stack = createStackNavigator();
  // タブ移動の設定を新規追加
  // createBottomTabNavigator ... タブ移動を設定する関数
  const Tab = createBottomTabNavigator();

  // 新規追加
  // - 移動を関数に持たせて、タブ移動の設定で利用
  // - 意図 ... タブ移動の箇所のコードが読みにくくなるため
  const Home = () => {
    return (
      <Stack.Navigator>
        <Stack.Screen
          options={{ headerShown: false }}
          name="Home"
          component={HomeScreen}
        />
      </Stack.Navigator>
    );
  };

  const Post = () => {
    return (
      <Stack.Navigator
        headerMode="screen"
        screenOptions={{ headerShown: false }}
      >
        <Stack.Screen name="Post" component={PostScreen} />
        {/* <Stack.Screen name="詳細" component={DetailsScreen} /> */}
      </Stack.Navigator>
    );
  };

  const Profile = () => {
    return (
      <Stack.Navigator
        headerMode="screen"
        screenOptions={{ headerShown: false }}
      >
        <Stack.Screen name="Profile" component={ProfileScreen} />
        {/* <Stack.Screen name="詳細" component={DetailsScreen} /> */}
      </Stack.Navigator>
    );
  };

  return (
    <AuthContextProvider>
      <FirestoreContextProvider>
        <FormContextProvider>
          <NativeBaseProvider>
            <NavigationContainer theme={MyTheme}>
              <Tab.Navigator
                screenOptions={({ route }) => ({
                  tabBarIcon: ({ focused, color, size }) => {
                    let iconName;
                    // icon swithcer which depends on the route name
                    if (route.name === "Home") {
                      iconName = focused ? "ios-home" : "ios-home";
                    } else if (route.name === "Post") {
                      iconName = focused ? "ios-add" : "ios-add";
                    } else if (route.name === "Profile") {
                      iconName = focused ? "md-person" : "md-person";
                    }
                    return (
                      <Ionicons name={iconName} size={size} color={color} />
                    );
                  },
                })}
                tabBarOptions={{
                  activeTintColor: "rgb(0, 110, 182)",
                  inactiveTintColor: "gray",
                }}
              >
                <Tab.Screen name="Home" component={Home} />
                <Tab.Screen name="Post" component={Post} />
                <Tab.Screen name="Profile" component={Profile} />
              </Tab.Navigator>
            </NavigationContainer>
          </NativeBaseProvider>
        </FormContextProvider>
      </FirestoreContextProvider>
    </AuthContextProvider>
  );
}

最佳答案

这是因为,即使您切换屏幕,另一个屏幕也不会被卸载——它仍然在内存中但不可见。这是 react 导航的设计决策,旨在获得更好的性能(当您返回时,它不必重新加载屏幕,因为它已经在那里)。由于它没有被卸载,当用户返回到它时,它只是触发了已经实例化的组件的重新渲染,因此效果不会运行。

您需要使用的是 useFocusEffect这是屏幕聚焦时绑定(bind)的效果。

关于javascript - 切换屏幕时 useEffect 不起作用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/74672780/

相关文章:

javascript - 为什么我的 $().css({ "visibility": "visible"}) working?

javascript - 为什么 Button 组件在单击时改变位置?

reactjs - 在 React 组件中动态导入图像

javascript - 如何从子模块访问父方法?

javascript - 在 Knockout Foreach 循环中生成 ID

javascript - javascript中静态方法的名称不能重复?

react-native - 无法解析模块 react-native/Libraries/Components/View/ViewStylePropTypes

react-native - 如何定义 React Native 应用程序的入口点

javascript - 有人可以解释如何正确编写这个 Javascript 程序吗?

d3.js - Reactjs 与 D3js 树形图