Skip to content

Commit 2202a56

Browse files
committed
allow using LinkEvent in router <Link /> component
1 parent 021635d commit 2202a56

File tree

3 files changed

+77
-10
lines changed

3 files changed

+77
-10
lines changed

packages/inferno-router/__tests__/Link.spec.tsx

Lines changed: 63 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { Component, InfernoNode, render } from 'inferno';
1+
import {Component, InfernoNode, linkEvent, render} from 'inferno';
22
import { HashRouter, Link, MemoryRouter } from 'inferno-router';
33
import { createMemoryHistory, parsePath } from 'history';
44

@@ -120,6 +120,68 @@ describe('A <Link> underneath a <HashRouter>', () => {
120120
expect(a.getAttribute('href')).toEqual('/the/path?the=query#the-hash');
121121
});
122122

123+
it('accepts an object `to` prop with state', () => {
124+
const memoryHistoryFoo = createMemoryHistory({
125+
initialEntries: ['/foo'],
126+
});
127+
memoryHistoryFoo.push = jasmine.createSpy();
128+
129+
// clickHandler is the linkEvent handler
130+
let called = false;
131+
const clickHandler = linkEvent({a: 1}, (data, event) => {
132+
expect(data).toBeDefined();
133+
expect(data.a).toEqual(1);
134+
expect(event).toBeDefined();
135+
expect((event as any).type).toEqual('click');
136+
called = true;
137+
});
138+
139+
const to = {
140+
hash: '#the-hash2',
141+
key: '2',
142+
pathname: '/the/path2',
143+
search: 'the=query2',
144+
state: { test: 'ok2' },
145+
};
146+
147+
class ContextChecker extends Component<{ children?: InfernoNode }> {
148+
public getChildContext() {
149+
const { context } = this;
150+
context.router.history = memoryHistoryFoo;
151+
152+
return {
153+
router: context.router,
154+
};
155+
}
156+
157+
public render({ children }) {
158+
return children;
159+
}
160+
}
161+
162+
render(
163+
<MemoryRouter>
164+
<ContextChecker>
165+
<Link to={to} onClick={clickHandler}>
166+
link
167+
</Link>
168+
</ContextChecker>
169+
</MemoryRouter>,
170+
node,
171+
);
172+
173+
const a = node.querySelector('a');
174+
a.click();
175+
176+
expect(called).toBeTruthy();
177+
expect(memoryHistoryFoo.push).toHaveBeenCalledTimes(1);
178+
const { hash, key, pathname, search, state } = to;
179+
expect(memoryHistoryFoo.push).toHaveBeenCalledWith(
180+
{ hash, key, pathname, search },
181+
state,
182+
);
183+
});
184+
123185
it('accepts an object `to` prop with state', () => {
124186
const memoryHistoryFoo = createMemoryHistory({
125187
initialEntries: ['/foo'],

packages/inferno-router/src/Link.ts

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
11
import {
22
createVNode,
33
type Inferno,
4-
type InfernoMouseEvent,
4+
type InfernoMouseEvent, LinkedEvent,
55
linkEvent,
66
type VNode,
77
} from 'inferno';
88
import { ChildFlags, VNodeFlags } from 'inferno-vnode-flags';
99
import { invariant } from './utils';
10-
import { isString } from 'inferno-shared';
10+
import {isFunction, isString} from 'inferno-shared';
1111
import type { Location } from 'history';
1212
import { parsePath } from 'history';
1313
import { normalizeToLocation, splitLocation } from './locationUtils';
@@ -17,7 +17,7 @@ const isModifiedEvent = (event: InfernoMouseEvent<any>): boolean =>
1717

1818
export interface ILinkProps {
1919
children?: any;
20-
onClick?: any;
20+
onClick?: ((event: MouseEvent) => void) | LinkedEvent<any, any> | null;
2121
target?: string;
2222
className?: string;
2323
replace?: boolean;
@@ -26,8 +26,13 @@ export interface ILinkProps {
2626
}
2727

2828
function handleClick({ props, context }, event: InfernoMouseEvent<any>): void {
29-
if (props.onClick) {
30-
props.onClick(event);
29+
const onClick = props.onClick;
30+
if (onClick) {
31+
if (isFunction(onClick)) {
32+
onClick(event);
33+
} else if (isFunction(onClick.event)) {
34+
onClick.event(onClick.data, event);
35+
}
3136
}
3237

3338
if (

packages/inferno/src/DOM/events/linkEvent.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,15 +4,15 @@ import { isFunction, isNull } from 'inferno-shared';
44
/**
55
* Links given data to event as first parameter
66
* @param {*} data data to be linked, it will be available in function as first parameter
7-
* @param {Function} event Function to be called when event occurs
7+
* @param {Function} callback Function to be called when event occurs
88
* @returns {{data: *, event: Function}}
99
*/
1010
export function linkEvent<T, E extends Event>(
1111
data: T,
12-
event: (data: T, event: E) => void,
12+
callback: (data: T, event: E) => void,
1313
): LinkedEvent<T, E> | null {
14-
if (isFunction(event)) {
15-
return { data, event };
14+
if (isFunction(callback)) {
15+
return { data, event: callback };
1616
}
1717
return null; // Return null when event is invalid, to avoid creating unnecessary event handlers
1818
}

0 commit comments

Comments
 (0)