React组件保留先前状态

gajydyqb  于 2022-12-30  发布在  React
关注(0)|答案(1)|浏览(153)

我学习ReactReact Native还不到一个星期,所以有些概念我还在学习中。下面的代码是第一次尝试编写一个通过底部标签导航器导航的应用程序,更具体地说,使用@react-navigation/material-bottom-tabsreact-native-paper。有3个屏幕,分别称为主页、详细信息和帮助。主页和详细信息都包含一个按钮"寻求帮助",这两个选项都将重定向到"帮助"屏幕,并带有作为参数传递的特殊消息。例如:

<Button
        icon="camera"
        mode="contained"
        onPress={() => navigation.navigate("Help", { txt: "Everything is OK!" })}
        style={{ marginTop: 16 }}
      >
        Ask for help
      </Button>

加载应用程序时,HelpScreeninitialParams={{ txt: "nothing" }}启动,屏幕将显示You said nothing。从HomeScreen,单击按钮将我重定向到HelpScreen,显示onPress={() => navigation.navigate("Help", { txt: "Everything is OK!" })}。因此屏幕将显示You said Everything is OK!。使用底部选项卡移动到另一个屏幕,然后返回HelpScreen时,我希望HelpScreen用它的原始值重新呈现。因此我希望屏幕显示You said nothing。但是没有,它仍然显示You said Everything is OK!。同样的行为发生在DetailsScreen与另一个文本。
HelpScreen函数中,我没有将参数保存到一个状态。所以我不希望组件在重新渲染时保留以前的值。那么为什么组件在重新渲染时没有重置为原始值?或者它没有重新渲染?在这种情况下,您能否解释一下原因?
下面是代码:

import { registerRootComponent } from "expo";
import { NavigationContainer } from "@react-navigation/native";
import { NativeStackScreenProps } from "@react-navigation/native-stack";
import { createMaterialBottomTabNavigator } from "@react-navigation/material-bottom-tabs";
import { View } from "react-native";
import { Button, Text } from "react-native-paper";
import { SafeAreaProvider } from "react-native-safe-area-context";
import MaterialCommunityIcons from "react-native-vector-icons/MaterialCommunityIcons";

type NavigationParamList = {
  Home: undefined;
  Details: undefined;
  Help: { txt: string };
};

type PropsHome = NativeStackScreenProps<NavigationParamList, "Home">;
type PropsDetails = NativeStackScreenProps<NavigationParamList, "Details">;
type PropsHelp = NativeStackScreenProps<NavigationParamList, "Help">;

const Tab = createMaterialBottomTabNavigator<NavigationParamList>();

function HomeScreen({ navigation, route }: PropsHome) {
  console.log("HOME");
  return (
    <View style={{ flex: 1, justifyContent: "center", alignItems: "center" }}>
      <Text>Route name: {route.name}</Text>
      <Button
        icon="camera"
        mode="contained"
        onPress={() =>
          navigation.navigate("Help", { txt: "Everything is OK!" })
        }
        style={{ marginTop: 16 }}
      >
        Ask for help
      </Button>
    </View>
  );
}

function DetailsScreen({ navigation, route }: PropsDetails) {
  console.log("DETAILS");
  return (
    <View style={{ flex: 1, justifyContent: "center", alignItems: "center" }}>
      <Text>Route name: {route.name}</Text>
      <Button
        icon="camera"
        mode="contained"
        onPress={() => navigation.navigate("Help", { txt: "HELP ME!" })}
        style={{ marginTop: 16 }}
      >
        Ask for help
      </Button>
    </View>
  );
}

function HelpScreen({ route }: PropsHelp) {
  console.log("HELP");
  return (
    <View style={{ flex: 1, justifyContent: "center", alignItems: "center" }}>
      <Text>Route name: {route.name}</Text>
      <Text>You said {route.params.txt}</Text>
    </View>
  );
}

export default function App() {
  return (
    <SafeAreaProvider>
      <NavigationContainer>
        <Tab.Navigator initialRouteName="Home" screenOptions={{}}>
          <Tab.Screen
            name="Home"
            options={{
              tabBarIcon: ({ color }) => (
                <MaterialCommunityIcons name="home" color={color} size={26} />
              ),
            }}
            component={HomeScreen}
          />
          <Tab.Screen
            name="Details"
            options={{
              tabBarIcon: ({ color }) => (
                <MaterialCommunityIcons
                  name="alien-outline"
                  color={color}
                  size={26}
                />
              ),
            }}
            component={DetailsScreen}
          />
          <Tab.Screen
            name="Help"
            options={{
              tabBarIcon: ({ color }) => (
                <MaterialCommunityIcons
                  name="chat-question-outline"
                  color={color}
                  size={26}
                />
              ),
            }}
            component={HelpScreen}
            initialParams={{ txt: "nothing" }}
          />
        </Tab.Navigator>
      </NavigationContainer>
    </SafeAreaProvider>
  );
}

registerRootComponent(App);

注意,我没有使用useState钩子,我知道当你想保留一个值而不是重置它时,这个钩子是需要的。

agxfikkp

agxfikkp1#

React Navigation避免了每次聚焦时重新呈现每个屏幕,以获得更好的用户体验并避免不必要的屏幕重新呈现。
您应该覆盖此默认行为,并检测屏幕何时被重新访问/聚焦并重新呈现该屏幕。
它提供了实用程序钩子来监听屏幕是否聚焦-https://reactnavigation.org/docs/function-after-focusing-screen/
下面是一个代码重构解决方案:

import { registerRootComponent } from "expo";
import {useEffect,useState} from "react"
import { NavigationContainer ,useIsFocused} from "@react-navigation/native";
import { NativeStackScreenProps } from "@react-navigation/native-stack";
import { createMaterialBottomTabNavigator } from "@react-navigation/material-bottom-tabs";
import { View } from "react-native";
import { Button, Text } from "react-native-paper";
import { SafeAreaProvider } from "react-native-safe-area-context";
import MaterialCommunityIcons from "react-native-vector-icons/MaterialCommunityIcons";

type NavigationParamList = {
  Home: undefined;
  Details: undefined;
  Help: { txt: string };
};

type PropsHome = NativeStackScreenProps<NavigationParamList, "Home">;
type PropsDetails = NativeStackScreenProps<NavigationParamList, "Details">;
type PropsHelp = NativeStackScreenProps<NavigationParamList, "Help">;

const Tab = createMaterialBottomTabNavigator();
function HomeScreen({ navigation, route }: PropsHome) {
  console.log("HOME");
  return (
    <View style={{ flex: 1, justifyContent: "center", alignItems: "center" }}>
      <Text>Route name: {route.name}</Text>
      <Button
        icon="camera"
        mode="contained"
        onPress={() =>
          navigation.navigate("Help", { txt: "Everything is OK!" })
        }
        style={{ marginTop: 16 }}
      >
        Ask for help
      </Button>
    </View>
  );
}

function DetailsScreen({ navigation, route }: PropsDetails) {
  console.log("DETAILS");

  return (
    <View style={{ flex: 1, justifyContent: "center", alignItems: "center" }}>
      <Text>Route name: {route.name}</Text>
      <Button
        icon="camera"
        mode="contained"
        onPress={() => navigation.navigate("Help", { txt: "HELP ME!" })}
        style={{ marginTop: 16 }}
      >
        Ask for help
      </Button>
    </View>
  );
}

function HelpScreen({ route ,navigation}: PropsHelp) {
  const [message,setMessage] = useState("")

const isFocused = useIsFocused()
  useEffect(()=>{
setMessage(route.params.txt)
return ()=>{
  navigation.setParams({txt:"nothing"})
}
  },[isFocused])
  return (
    <View style={{ flex: 1, justifyContent: "center", alignItems: "center" }}>
      <Text>Route name: {route.name}</Text>
      <Text>You said {message}</Text>
    </View>
  );
}

export default function App() {
  return (
    <SafeAreaProvider>
      <NavigationContainer>
        <Tab.Navigator initialRouteName="Home" screenOptions={{}}>
          <Tab.Screen
            name="Home"
            options={{
              tabBarIcon: ({ color }) => (
                <MaterialCommunityIcons name="home" color={color} size={26} />
              ),
            }}
            component={HomeScreen}
          />
          <Tab.Screen
            name="Details"
            options={{
              tabBarIcon: ({ color }) => (
                <MaterialCommunityIcons
                  name="alien-outline"
                  color={color}
                  size={26}
                />
              ),
            }}
            component={DetailsScreen}
          />
          <Tab.Screen
            name="Help"
            options={{
              tabBarIcon: ({ color }) => (
                <MaterialCommunityIcons
                  name="chat-question-outline"
                  color={color}
                  size={26}
                />
              ),
            }}
            component={HelpScreen}
            initialParams={{ txt: "nothing" }}
          />
        </Tab.Navigator>
      </NavigationContainer>
    </SafeAreaProvider>
  );
}

工作演示-https://snack.expo.dev/@emmbyiringiro/493761

相关问题