Skip to content
This repository has been archived by the owner on Feb 8, 2020. It is now read-only.

Commit

Permalink
feat: improve types for options and support a function
Browse files Browse the repository at this point in the history
  • Loading branch information
satya164 committed Jul 22, 2019
1 parent 51200ba commit 62f4047
Show file tree
Hide file tree
Showing 9 changed files with 72 additions and 36 deletions.
6 changes: 5 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -173,7 +173,11 @@ And then we can use it:
```js
<Stack.Navigator initialRouteName="profile">
<Stack.Screen name="settings" component={Settings} />
<Stack.Screen name="profile" component={Profile} />
<Stack.Screen
name="profile"
component={Profile}
options={{ title: 'My profile' }}
/>
<Stack.Screen name="home" component={Home} />
</Stack.Navigator>
```
Expand Down
16 changes: 14 additions & 2 deletions example/StackNavigator.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,13 @@ type Action =
}
| { type: 'POP_TO_TOP' };

export type StackNavigationOptions = {
/**
* Title text for the screen.
*/
title?: string;
};

export type StackNavigationProp<
ParamList extends ParamListBase
> = NavigationProp<ParamList> & {
Expand Down Expand Up @@ -236,7 +243,10 @@ const StackRouter: Router<CommonAction | Action> = {
};

export function StackNavigator(props: Props) {
const { state, descriptors } = useNavigationBuilder(StackRouter, props);
const { state, descriptors } = useNavigationBuilder<StackNavigationOptions>(
StackRouter,
props
);

return (
<div style={{ position: 'relative' }}>
Expand Down Expand Up @@ -277,4 +287,6 @@ export function StackNavigator(props: Props) {
);
}

export default createNavigator(StackNavigator);
export default createNavigator<StackNavigationOptions, typeof StackNavigator>(
StackNavigator
);
11 changes: 10 additions & 1 deletion example/TabNavigator.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,13 @@ type Action = {
payload: { name?: string; key?: string; params?: object };
};

export type TabNavigationOptions = {
/**
* Title text for the screen.
*/
title?: string;
};

export type TabNavigationProp<ParamList extends ParamListBase> = NavigationProp<
ParamList
> & {
Expand Down Expand Up @@ -196,4 +203,6 @@ export function TabNavigator(props: Props) {
);
}

export default createNavigator(TabNavigator);
export default createNavigator<TabNavigationOptions, typeof TabNavigator>(
TabNavigator
);
12 changes: 6 additions & 6 deletions example/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -149,14 +149,14 @@ function App() {
<MyStack.Screen
name="first"
component={First}
options={{ title: 'Foo' }}
options={({ route }) => ({
title: `Foo (${route.params ? route.params.author : ''})`,
})}
initialParams={{ author: 'Jane' }}
/>
<MyStack.Screen
name="second"
component={Second}
options={{ title: 'Bar' }}
/>
<MyStack.Screen name="second" options={{ title: 'Bar' }}>
{props => <Second {...props} />}
</MyStack.Screen>
<MyStack.Screen name="third" options={{ title: 'Baz' }}>
{() => (
<MyTab.Navigator initialRouteName="fifth">
Expand Down
9 changes: 7 additions & 2 deletions src/SceneView.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,13 @@ type Props = {
setState: (state: NavigationState) => void;
};

export default function SceneView(props: Props) {
const { screen, route, navigation: helpers, getState, setState } = props;
export default function SceneView({
screen,
route,
navigation: helpers,
getState,
setState,
}: Props) {
const { performTransaction } = React.useContext(NavigationStateContext);

const navigation = React.useMemo(
Expand Down
10 changes: 6 additions & 4 deletions src/createNavigator.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,19 @@ import * as React from 'react';
import { ParamListBase, RouteConfig, TypedNavigator } from './types';
import Screen from './Screen';

export default function createNavigator<N extends React.ComponentType<any>>(
RawNavigator: N
) {
export default function createNavigator<
Options extends object,
N extends React.ComponentType<any>
>(RawNavigator: N) {
return function Navigator<ParamList extends ParamListBase>(): TypedNavigator<
ParamList,
Options,
typeof RawNavigator
> {
return {
Navigator: RawNavigator,
Screen: Screen as React.ComponentType<
RouteConfig<ParamList, keyof ParamList>
RouteConfig<ParamList, keyof ParamList, Options>
>,
};
};
Expand Down
24 changes: 11 additions & 13 deletions src/types.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -232,7 +232,7 @@ export type CompositeNavigationProp<
(B extends NavigationProp<infer U> ? U : never)
>;

export type Descriptor = {
export type Descriptor<Options extends object> = {
/**
* Render the component associated with this route.
*/
Expand All @@ -244,18 +244,10 @@ export type Descriptor = {
options: Options;
};

export type Options = {
/**
* Title text for the screen.
*/
title?: string;

[key: string]: any;
};

export type RouteConfig<
ParamList extends ParamListBase = ParamListBase,
RouteName extends keyof ParamList = string
RouteName extends keyof ParamList = string,
Options extends object = object
> = {
/**
* Route name of this screen.
Expand All @@ -265,7 +257,12 @@ export type RouteConfig<
/**
* Navigator options for this screen.
*/
options?: Options;
options?:
| Options
| ((props: {
route: RouteProp<ParamList, RouteName>;
navigation: NavigationProp<ParamList>;
}) => Options);

/**
* Initial params object for the route.
Expand All @@ -287,6 +284,7 @@ export type RouteConfig<

export type TypedNavigator<
ParamList extends ParamListBase,
Options extends object,
Navigator extends React.ComponentType<any>
> = {
Navigator: React.ComponentType<
Expand All @@ -297,5 +295,5 @@ export type TypedNavigator<
initialRouteName?: keyof ParamList;
}
>;
Screen: React.ComponentType<RouteConfig<ParamList, keyof ParamList>>;
Screen: React.ComponentType<RouteConfig<ParamList, keyof ParamList, Options>>;
};
16 changes: 11 additions & 5 deletions src/useDescriptors.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,7 @@ type Options = {
onRouteFocus: (key: string) => void;
};

const EMPTY_OPTIONS = Object.freeze({});

export default function useDescriptors({
export default function useDescriptors<ScreenOptions extends object>({
state,
screens,
navigation,
Expand Down Expand Up @@ -73,10 +71,18 @@ export default function useDescriptors({
</NavigationBuilderContext.Provider>
);
},
options: screen.options || EMPTY_OPTIONS,
options: {
...(typeof screen.options === 'function'
? screen.options({
// @ts-ignore
route,
navigation,
})
: screen.options),
},
};
return acc;
},
{} as { [key: string]: Descriptor }
{} as { [key: string]: Descriptor<ScreenOptions> }
);
}
4 changes: 2 additions & 2 deletions src/useNavigationBuilder.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ const getRouteConfigsFromChildren = (children: React.ReactNode) =>
);
}, []);

export default function useNavigationBuilder(
export default function useNavigationBuilder<ScreenOptions extends object>(
router: Router<any>,
options: Options
) {
Expand Down Expand Up @@ -156,7 +156,7 @@ export default function useNavigationBuilder(
actionCreators: router.actionCreators,
});

const descriptors = useDescriptors({
const descriptors = useDescriptors<ScreenOptions>({
state,
screens,
navigation,
Expand Down

0 comments on commit 62f4047

Please sign in to comment.