Some changes to react-navigation

This commit is contained in:
doomsower
2018-03-23 16:49:30 +03:00
parent f2982c1754
commit f2b858e68f
2 changed files with 73 additions and 10 deletions

View File

@@ -77,7 +77,7 @@ export interface NavigationState {
export type NavigationRoute = NavigationLeafRoute | NavigationStateRoute;
export interface NavigationLeafRoute {
export interface NavigationLeafRoute<P extends NavigationParams = NavigationParams> {
/**
* React's key used by some navigators. No need to specify these manually,
* they will be defined by the router.
@@ -96,7 +96,7 @@ export interface NavigationLeafRoute {
* Params passed to this route when navigating to it,
* e.g. `{ car_id: 123 }` in a route that displays a car.
*/
params?: NavigationParams;
params?: P;
}
export type NavigationStateRoute = NavigationLeafRoute & NavigationState;
@@ -175,6 +175,7 @@ export type NavigationScreenConfig<Options> =
export type NavigationComponent =
NavigationScreenComponent<any, any>
| NavigationStatelessScreen
| NavigationNavigator<any, any, any, any>;
export interface NavigationScreenComponent<T, Options> extends React.ComponentClass<T> {
@@ -299,7 +300,7 @@ export interface NavigationStackRouterConfig {
initialRouteName?: string;
initialRouteParams?: NavigationParams;
paths?: NavigationPathsConfig;
navigationOptions?: NavigationScreenConfig<NavigationStackScreenOptions>;
navigationOptions?: NavigationScreenConfig<AnyScreenOptions>;
}
export type NavigationStackAction =
@@ -339,7 +340,7 @@ export interface NavigationPathsConfig {
export interface NavigationTabRouterConfig {
initialRouteName?: string;
paths?: NavigationPathsConfig;
navigationOptions?: NavigationScreenConfig<NavigationTabScreenOptions>;
navigationOptions?: NavigationScreenConfig<AnyScreenOptions>;
order?: string[]; // todo: type these as the real route names rather than 'string'
// Does the back button cause the router to switch to the initial tab
@@ -433,7 +434,8 @@ export interface NavigationScreenProp<S, P = NavigationParams> {
params?: P,
action?: NavigationAction,
): boolean;
setParams: (newParams: NavigationParams) => boolean;
getParam: <T extends keyof P>(param: T, fallback?: P[T]) => P[T];
setParams: (newParams: P) => boolean;
addListener: (
eventName: string,
callback: NavigationEventCallback
@@ -853,12 +855,25 @@ export function createNavigationContainer(
* BEGIN CUSTOM CONVENIENCE INTERFACES
*/
export interface NavigationScreenProps {
navigation: NavigationScreenProp<NavigationRoute>;
export interface NavigationScreenProps<P extends NavigationParams = NavigationParams> {
navigation: NavigationScreenProp<NavigationRoute, P>;
screenProps?: { [key: string]: any };
navigationOptions?: NavigationScreenConfig<any>;
navigationOptions?: NavigationScreenConfig<AnyScreenOptions>;
}
export type AnyScreenOptions =
NavigationDrawerScreenOptions &
NavigationStackScreenOptions &
NavigationTabScreenOptions;
export interface NavigationScreenStatic<Options = AnyScreenOptions> {
navigationOptions?: NavigationScreenConfig<Options>;
}
export type NavigationStatelessScreen<Props = {}, Params = {}, NavOptions = AnyScreenOptions> =
React.StatelessComponent<Props & NavigationScreenProps<Params>> &
NavigationScreenStatic<NavOptions>;
/**
* END CUSTOM CONVENIENCE INTERFACES
*/

View File

@@ -36,6 +36,10 @@ import {
NavigationParams,
NavigationPopAction,
NavigationPopToTopAction,
NavigationScreenStatic,
NavigationScreenConfig,
AnyScreenOptions,
NavigationStatelessScreen,
} from 'react-navigation';
// Constants
@@ -84,12 +88,24 @@ class StartScreen extends React.Component<NavigationScreenProps> {
const ROUTE_NAME_NEXT_SCREEN = "NextScreen";
class NextScreen extends React.Component<NavigationScreenProps> {
interface NextScreenParams {
id: string;
name: string;
}
class NextScreen extends React.Component<NavigationScreenProps<NextScreenParams>> {
static navigationOptions: NavigationScreenConfig<AnyScreenOptions> = {
tabBarLabel: 'Next tab',
drawerLabel: 'Next drawe label',
};
render() {
// Implicit type checks.
const navigationStateParams = this.props.navigation.state.params;
// typeof id is any
const id = this.props.navigation.state.params && this.props.navigation.state.params.id;
const name = this.props.navigation.state.params && this.props.navigation.state.params.name;
// typeof name is string
const name = this.props.navigation.getParam('name', 'Peter');
return (
<View />
@@ -97,6 +113,29 @@ class NextScreen extends React.Component<NavigationScreenProps> {
}
}
const ROUTE_NAME_ANOTHER_SCREEN = "AnotherScreen";
interface AnotherScreenParams {
color: string;
}
interface AnotherScreenProps {
apolloData: number[]; // Demonstrates that screen can be wrapped into HOCs
}
// View below compiles without TS errors, because props and navigation params are strongly typed
const AnotherScreen: NavigationStatelessScreen<AnotherScreenProps, AnotherScreenParams> = ({ apolloData, navigation }) => (
<View
style={{ backgroundColor: navigation.getParam('color', 'red')}}
hitSlop={{ left: apolloData[0], right: apolloData[1] }}
/>
)
// Demonstrates overriding navigationOptions on static components
AnotherScreen.navigationOptions = ({ navigation, navigationOptions }) => ({
drawerLabel: navigation.state.params!.color + ' screen',
});
const navigationOptions = {
headerBackTitle: null,
};
@@ -113,6 +152,15 @@ const routeConfigMap: NavigationRouteConfigMap = {
path: "next",
screen: NextScreen,
},
// Demonstrates stateless screen
[ROUTE_NAME_ANOTHER_SCREEN]: {
path: "another",
screen: AnotherScreen,
navigationOptions: {
// Demonstrates that stack entries can set optins for tab navigation (for deeper use)
tabBarVisible: false,
}
},
};
export const AppNavigator = StackNavigator(
routeConfigMap,