Skip to content

Commit 9706b56

Browse files
authored
Allow custom router selector arguments + fix RouteResourceUpdater type (#95)
1 parent 2f82194 commit 9706b56

File tree

4 files changed

+39
-9
lines changed

4 files changed

+39
-9
lines changed

src/__tests__/unit/controllers/router-store/test.tsx

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -789,7 +789,8 @@ describe('SPA Router store', () => {
789789

790790
describe('createRouterSelector', () => {
791791
it('should return selected state', () => {
792-
const useRouteName = createRouterSelector(s => s.route.name);
792+
const mockSelector = jest.fn().mockImplementation(s => s.route.name);
793+
const useRouteName = createRouterSelector(mockSelector);
793794
const RouteName = () => <>{useRouteName()}</>;
794795
const route = { path: '', name: 'home', component: () => null };
795796

@@ -799,6 +800,31 @@ describe('SPA Router store', () => {
799800
</MemoryRouter>
800801
);
801802

803+
expect(mockSelector).toBeCalledWith(
804+
expect.objectContaining({ route }),
805+
undefined
806+
);
807+
expect(wrapper.html()).toEqual('home');
808+
});
809+
810+
it('should pass through single hook argument to selector', () => {
811+
const mockSelector = jest.fn().mockImplementation(s => s.route.name);
812+
const useRouteName = createRouterSelector(mockSelector);
813+
const RouteName = ({ argument }: { argument: unknown }) => (
814+
<>{useRouteName(argument)}</>
815+
);
816+
const route = { path: '', name: 'home', component: () => null };
817+
818+
const wrapper = mount(
819+
<MemoryRouter routes={[route]}>
820+
<RouteName argument="bar" />
821+
</MemoryRouter>
822+
);
823+
824+
expect(mockSelector).toBeCalledWith(
825+
expect.objectContaining({ route }),
826+
'bar'
827+
);
802828
expect(wrapper.html()).toEqual('home');
803829
});
804830
});

src/controllers/router-store/index.tsx

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -426,14 +426,18 @@ export const useRouterStoreStatic = createHook<
426426
/**
427427
* Utility to create custom hooks without re-rendering on route change
428428
*/
429-
export function createRouterSelector<T>(selector: (state: RouterState) => T) {
430-
const useHook = createHook<EntireRouterState, AllRouterActions, T>(
429+
export function createRouterSelector<T, U = void>(
430+
selector: (state: RouterState, props: U) => T
431+
) {
432+
const useHook = createHook<EntireRouterState, AllRouterActions, T, U>(
431433
RouterStore,
432434
{ selector }
433435
);
434436

435-
return function useRouterSelector() {
436-
return useHook()[0];
437+
return function useRouterSelector(
438+
...args: U extends undefined ? [] : [U]
439+
): T {
440+
return useHook(...args)[0];
437441
};
438442
}
439443

src/index.js.flow

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -80,9 +80,9 @@ declare export function useResource<T>(
8080
declare export function useRouter(): [RouterState, RouterActionsType];
8181
declare export function useRouterActions(): RouterActionsType;
8282
declare export function useResourceStoreContext(): ResourceStoreContext;
83-
declare export function createRouterSelector<T>(
84-
selector: (state: RouterState) => T
85-
): () => T;
83+
declare export function createRouterSelector<T, U = void>(
84+
selector: (state: RouterState, props: U) => T
85+
): (U) => T;
8686

8787
declare export function useQueryParam(
8888
paramKey: string

src/types.js.flow

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -100,7 +100,7 @@ export type ResourceOptions = {
100100
routerContext?: RouterContext,
101101
};
102102

103-
export type RouteResourceUpdater<T: RouteResourceData<any>> = (data: T) => T;
103+
export type RouteResourceUpdater<T> = (data: RouteResourceData<T>) => RouteResourceData<T>;
104104

105105
export type InvariantRoute = {
106106
path: string,

0 commit comments

Comments
 (0)