Front: Navigation: Route Props include route info

This commit is contained in:
Arthur Jamet
2023-04-16 16:01:12 +01:00
committed by Clément Le Bihan
parent 6871aaf759
commit deaaaac2cd
5 changed files with 25 additions and 20 deletions

View File

@@ -1,5 +1,5 @@
import { NativeStackScreenProps, createNativeStackNavigator } from '@react-navigation/native-stack';
import { NavigationProp, useNavigation as navigationHook } from "@react-navigation/native";
import { NavigationProp, ParamListBase, useNavigation as navigationHook } from "@react-navigation/native";
import React from 'react';
import { DarkTheme, DefaultTheme, NavigationContainer } from '@react-navigation/native';
import { RootState, useSelector } from './state/Store';
@@ -19,6 +19,7 @@ import LoadingComponent from './components/Loading';
import ProfileView from './views/ProfileView';
import useColorScheme from './hooks/colorScheme';
const protectedRoutes = () => ({
Home: { component: HomeView, options: { title: translate('welcome') } },
Settings: { component: SetttingsNavigator, options: { title: 'Settings' } },
@@ -34,13 +35,15 @@ const publicRoutes = () => ({
Login: { component: AuthenticationView, options: { title: translate('signInBtn') } },
}) as const;
type Route<Args extends any[] = any[]> = {
component: (...args: Args) => JSX.Element,
type Route<Props = any> = {
component: (arg: RouteProps<Props>) => JSX.Element | (() => JSX.Element),
options: any
}
type OmitOrUndefined<T, K extends string> = T extends undefined ? T : Omit<T, K>
type RouteParams<Routes extends Record<string, Route>> = {
[RouteName in keyof Routes]: Parameters<Routes[RouteName]['component']>[0];
[RouteName in keyof Routes]: OmitOrUndefined<Parameters<Routes[RouteName]['component']>[0], keyof NativeStackScreenProps<{}>>;
}
type PrivateRoutesParams = RouteParams<ReturnType<typeof protectedRoutes>>;
@@ -49,12 +52,12 @@ type AppRouteParams = PrivateRoutesParams & PublicRoutesParams;
const Stack = createNativeStackNavigator<AppRouteParams & { Loading: never }>();
const RouteToScreen = (component: Route['component']) => (props: NativeStackScreenProps<AppRouteParams>) =>
const RouteToScreen = <T extends {}, >(component: Route<T>['component']) => (props: NativeStackScreenProps<T & ParamListBase>) =>
<>
{component(props.route.params)}
{component({ ...props.route.params, route: props.route } as Parameters<Route<T>['component']>[0])}
</>
const routesToScreens = (routes: Record<keyof AppRouteParams, Route>) => Object.entries(routes)
const routesToScreens = (routes: Partial<Record<keyof AppRouteParams, Route>>) => Object.entries(routes)
.map(([name, route]) => (
<Stack.Screen
name={name as keyof AppRouteParams}
@@ -92,4 +95,7 @@ export const Router = () => {
);
}
export type RouteProps<T> = T & Pick<NativeStackScreenProps<T & ParamListBase>, 'route'>;
export const useNavigation = () => navigationHook<NavigationProp<AppRouteParams>>();

View File

@@ -7,7 +7,7 @@ import { Center, Button, Text } from 'native-base';
import SigninForm from "../components/forms/signinform";
import SignupForm from "../components/forms/signupform";
import TextButton from "../components/TextButton";
import { useNavigation } from "../Navigation";
import { RouteProps } from "../Navigation";
const hanldeSignin = async (username: string, password: string, apiSetter: (accessToken: string) => void): Promise<string> => {
try {
@@ -33,15 +33,12 @@ const handleSignup = async (username: string, password: string, email: string, a
}
};
const AuthenticationView = () => {
const navigation = useNavigation();
type AuthenticationViewProps = {
isSignup: boolean;
}
const AuthenticationView = ({ isSignup }: RouteProps<AuthenticationViewProps>) => {
const dispatch = useDispatch();
console.log(navigation.getState());
const params = navigation.getState().routes.find((route) => {
// this is not ideal way to check if we are on login page
return route.name === "Login";
}).params ?? {};
const isSignup = params?.isSignup ?? false;
const [mode, setMode] = React.useState<"signin" | "signup">(isSignup ? "signup" : "signin");
return (

View File

@@ -33,7 +33,7 @@ if (process.env.NODE_ENV != 'development' && Platform.OS === 'web') {
}
}
const PlayView = ({ songId }: PlayViewProps) => {
const PlayView = ({ songId }: RouteProps<PlayViewProps>) => {
const navigation = useNavigation();
const queryClient = useQueryClient();
const song = useQuery(['song', songId], () => API.getSong(songId));

View File

@@ -1,14 +1,16 @@
import { Card, Column, Image, Row, Text, useTheme, ScrollView, Center, VStack } from "native-base"
import Translate from "../components/Translate";
import SongCardGrid from "../components/SongCardGrid";
import { useNavigation } from "../Navigation";
import { RouteProps, useNavigation } from "../Navigation";
import { CardBorderRadius } from "../components/Card";
import TextButton from "../components/TextButton";
import API from '../API';
import { useQuery } from "react-query";
import LoadingComponent from "../components/Loading";
const ScoreView = ({ songId }: { songId: number }) => {
type ScoreViewProps = { songId: number }
const ScoreView = ({ songId }: RouteProps<ScoreViewProps>) => {
const theme = useTheme();
const navigation = useNavigation();
// const songQuery = useQuery(['song', props.songId], () => API.getSong(props.songId));

View File

@@ -14,7 +14,7 @@ interface SongLobbyProps {
songId: number;
}
const SongLobbyView = (props: SongLobbyProps) => {
const SongLobbyView = (props: RouteProps<SongLobbyProps>) => {
const navigation = useNavigation();
const songQuery = useQuery(['song', props.songId], () => API.getSong(props.songId));
const chaptersQuery = useQuery(['song', props.songId, 'chapters'], () => API.getSongChapters(props.songId));