Skip to content

Instantly share code, notes, and snippets.

@emeraldsanto
Last active September 4, 2021 03:52
Show Gist options
  • Select an option

  • Save emeraldsanto/6efde1db9358f5a9979ba20776a95f5b to your computer and use it in GitHub Desktop.

Select an option

Save emeraldsanto/6efde1db9358f5a9979ba20776a95f5b to your computer and use it in GitHub Desktop.
Achieving type safe deep linking in React Native with react-navigation #8
/**
* Surprisingly, there is very little code here as all we really need to do
* is provide a short hand for the default render function of the provided screens.
*
* If a custom `render` is provided, we execute it by passing the whole configuration
* as props.
*
* Otherwise use the default behaviour defined in `renderScreens`.
*/
export function makeNavigator<
TNavigatorType extends NavigatorType,
TScreens extends ScreenMap
>(
config: PartialNavigatorConfiguration<TNavigatorType, TScreens>,
): NavigatorConfiguration<TNavigatorType, TScreens> {
if (config.render) {
const Component = config.render;
return {
...config,
render: () => <Component {...config} />,
};
}
const Parent = navigators[config.type]();
return {
...config,
render: () => (
<Parent.Navigator>
{renderScreens(Parent, config.screens)}
</Parent.Navigator>
);
};
}
/**
* This function loops through the `screens` object and
* returns an array of rendered screens with common options.
*/
export function renderScreens<TScreens extends ScreenMap>(
Navigator: TypedNavigator<any, any, any, any, any>,
screens: TScreens,
mapper?: (
entry: TScreens[keyof TScreens],
) => Omit<ComponentProps<typeof Navigator['Screen']>, 'children'>,
) {
return Object.entries(screens).map(([name, entry]) => (
// @ts-ignore due to an odd union type bug...
<Navigator.Screen
key={name}
name={name}
options={entry.options}
component={entry.screen}
initialParams={entry.initialParams}
{...mapper?.((entry as unknown) as TScreens[keyof TScreens])}
/>
));
}
/**
* This is a small utility to deep merge navigation options.
*/
export function mergeOptions<TOptions extends NavigatorProps<keyof typeof navigators>>(
...xs: Array<Partial<TOptions>>
): TOptions {
return xs.reduce<TOptions>((output, x) => {
return {
...output,
...x,
screenOptions: {
...output.screenOptions,
...x.screenOptions,
},
};
}, {} as TOptions);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment