javascript - How to properly type navigation passed as props with React-Navigation with expo - Stack Overflow

How do I properly type navigation passed as props to another ponent? As per the docsEach screen ponent

How do I properly type navigation passed as props to another ponent? As per the docs

Each screen ponent in your app is provided with the navigation prop automatically.

And also,

To type check our screens, we need to annotate the navigation prop and the route prop received by a screen.

type Props = NativeStackScreenProps<RootStackParamList, 'Profile'>;

I have a navigation ponent with router:

const App: React.FC = () => {
  const [userMetrics, setUserMetrics] = useState<UserMetrics>(null);
  const Stack = createNativeStackNavigator<RootStackParamList>();
  return (
    <UserMetricsContext.Provider value={{ userMetrics, setUserMetrics }}>
      <NavigationContainer>
        <Stack.Navigator initialRouteName="Home">
          <Stack.Screen name="Home" ponent={Home} />
          <Stack.Screen name="Tests" ponent={Tests} />
        </Stack.Navigator>
      </NavigationContainer>
    </UserMetricsContext.Provider>
  );
};

And in Home screen I want to receive navigation prop to pass it down further to form which have a button that will navigate to Tests ponent and pass form data as params:

interface Props {
  navigation: NativeStackScreenProps<RootStackParamList, "Home">;
}

export const Home: React.FC<Props> = ({ navigation }) => {
  const { setUserMetrics } =
    useContext<IUserMetricsContextType>(UserMetricsContext);
  return (
    <View style={styles.container}>
      <StatusBar style="auto" />
      <HealthCheckForm onSubmit={setUserMetrics} navigation={navigation} />
    </View>
  );
};

and now the problem starts to be visible in form ponent because typescript is assuming one level too much, I have typed the props like I did in the parent Home ponent like so:

interface Props {
  onSubmit: React.Dispatch<React.SetStateAction<UserMetrics>>;
  navigation: NativeStackScreenProps<RootStackParamList, "Home">;
}

and typescript wants me to use it like so:

  const submitHandler = (data: UserMetrics) => {
    onSubmit(data);
    navigation.navigation.navigate("Tests", { userMetrics: data });
    console.log(data);
  };

This is not working however, the correct - working and navigating usage is

navigation.navigate("Tests", { userMetrics: data });

and when I navigate to the Tests ponent and pass the params along, I don't know how to receive them in Test ponent. I am trying to do it analogically like so:

interface Props {
  navigation: NativeStackScreenProps<RootStackParamList, "Tests">;
}

export const Tests: React.FC<Props> = ({ navigation }) => {
  const { userMetrics } =
    useContext<IUserMetricsContextType>(UserMetricsContext);
  console.log({ params: navigation.route.params });
  return (
    <View>
      <DisplayList />
    </View>
  );
};

And I get yet another error about reading properties of undefined. Thanks

How do I properly type navigation passed as props to another ponent? As per the docs

Each screen ponent in your app is provided with the navigation prop automatically.

And also,

To type check our screens, we need to annotate the navigation prop and the route prop received by a screen.

type Props = NativeStackScreenProps<RootStackParamList, 'Profile'>;

I have a navigation ponent with router:

const App: React.FC = () => {
  const [userMetrics, setUserMetrics] = useState<UserMetrics>(null);
  const Stack = createNativeStackNavigator<RootStackParamList>();
  return (
    <UserMetricsContext.Provider value={{ userMetrics, setUserMetrics }}>
      <NavigationContainer>
        <Stack.Navigator initialRouteName="Home">
          <Stack.Screen name="Home" ponent={Home} />
          <Stack.Screen name="Tests" ponent={Tests} />
        </Stack.Navigator>
      </NavigationContainer>
    </UserMetricsContext.Provider>
  );
};

And in Home screen I want to receive navigation prop to pass it down further to form which have a button that will navigate to Tests ponent and pass form data as params:

interface Props {
  navigation: NativeStackScreenProps<RootStackParamList, "Home">;
}

export const Home: React.FC<Props> = ({ navigation }) => {
  const { setUserMetrics } =
    useContext<IUserMetricsContextType>(UserMetricsContext);
  return (
    <View style={styles.container}>
      <StatusBar style="auto" />
      <HealthCheckForm onSubmit={setUserMetrics} navigation={navigation} />
    </View>
  );
};

and now the problem starts to be visible in form ponent because typescript is assuming one level too much, I have typed the props like I did in the parent Home ponent like so:

interface Props {
  onSubmit: React.Dispatch<React.SetStateAction<UserMetrics>>;
  navigation: NativeStackScreenProps<RootStackParamList, "Home">;
}

and typescript wants me to use it like so:

  const submitHandler = (data: UserMetrics) => {
    onSubmit(data);
    navigation.navigation.navigate("Tests", { userMetrics: data });
    console.log(data);
  };

This is not working however, the correct - working and navigating usage is

navigation.navigate("Tests", { userMetrics: data });

and when I navigate to the Tests ponent and pass the params along, I don't know how to receive them in Test ponent. I am trying to do it analogically like so:

interface Props {
  navigation: NativeStackScreenProps<RootStackParamList, "Tests">;
}

export const Tests: React.FC<Props> = ({ navigation }) => {
  const { userMetrics } =
    useContext<IUserMetricsContextType>(UserMetricsContext);
  console.log({ params: navigation.route.params });
  return (
    <View>
      <DisplayList />
    </View>
  );
};

And I get yet another error about reading properties of undefined. Thanks

Share Improve this question asked Jan 6, 2022 at 11:47 sevenseven 1,7043 gold badges23 silver badges53 bronze badges
Add a ment  | 

1 Answer 1

Reset to default 6

There are solutions for nested Navigators (starting point here: https://reactnavigation/docs/nesting-navigators/). However, in this case I would suggest not making your HealthCheckForm have any awareness of the navigation state. Just pass it a standard onSubmit() prop and handle all the navigation within the Home ponent.

Also as a tip make sure to set up your RootStackParamList correctly so that the "tests" route is expecting {userMetrics: YourDataType}. Here is a random example of setting that up.

export type RootStackParamList = {
    myRouteName: undefined;
    tests: { userMetrics: MyDataType }; // TS now expects MyDataType on the props for tests route
    terminalAndMate: {
        departingTerminal: WSFTerminal;
        arrivingTerminal: WSFTerminal;
    };
...

I would also suggest typing your screen props this way instead of as an interface. NativeStackScreenProps can carry params as defined on the rootStackParamList:

type TestsScreenProps = NativeStackScreenProps<RootStackParamList, "tests">;

With those two changes, the tests screen should have props.route.params, which will contain MyDataType.

try: https://reactnavigation/docs/5.x/typescript/

-addition in regards to Seven's ment-

Take a look at the type declaration for NativeStackScreenProps.

export declare type NativeStackScreenProps<ParamList extends ParamListBase, RouteName extends keyof ParamList = string> = {
    navigation: NativeStackNavigationProp<ParamList, RouteName>;
    route: RouteProp<ParamList, RouteName>;
};

By making the interface as you did, you are saying the type of props for that ponent is

{ navigation: { navigation: NativeStackNavigation..etc , route: RouteProp }}

You can see that it is double nested and not necessary as the type provided by the library supports all of the functionality you need.

onsubmit Your onSubmit function would look something like this:

//home.tsx
const onSubmit = (data: YourDataType) => {
props.navigation.navigate("tests", { userMetrics: data});
}

return (
//...stuff
<YourFormComponent onSubmit={onSubmit} />

This way all your navigation is handled by home, which is on the same 'level' as tests, and you keep your navigation a little cleaner.

Shouldn't need any useEffect calls.

发布者:admin,转转请注明出处:http://www.yc00.com/questions/1744142791a4560280.html

相关推荐

发表回复

评论列表(0条)

  • 暂无评论

联系我们

400-800-8888

在线咨询: QQ交谈

邮件:admin@example.com

工作时间:周一至周五,9:30-18:30,节假日休息

关注微信