Skip to content

Commit ff6fcc7

Browse files
authored
Merge pull request #12 from preactjs/allow-updating-props
allow updating props
2 parents 7976c17 + 021df4c commit ff6fcc7

File tree

2 files changed

+60
-11
lines changed

2 files changed

+60
-11
lines changed

src/router.js

Lines changed: 9 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -118,24 +118,22 @@ export function Router(props) {
118118
const didSuspend = useRef();
119119
didSuspend.current = false;
120120

121-
cur.current = useMemo(() => {
121+
useMemo(() => {
122122
// This hack prevents Preact from diffing when we swap `cur` to `prev`:
123123
if (this.__v && this.__v.__k) this.__v.__k.reverse();
124124

125125
count.current++;
126-
127126
prev.current = cur.current;
128-
129-
let p, d, m;
130-
toChildArray(props.children).some(vnode => {
131-
const matches = exec(rest, vnode.props.path, (m = { ...vnode.props, path: rest, query, params, rest: '' }));
132-
if (matches) return (p = cloneElement(vnode, m));
133-
if (vnode.props.default) d = cloneElement(vnode, m);
134-
});
135-
136-
return h(RouteContext.Provider, { value: m }, p || d);
137127
}, [url]);
138128

129+
let pr, d, m;
130+
toChildArray(props.children).some(vnode => {
131+
const matches = exec(rest, vnode.props.path, (m = { ...vnode.props, path: rest, query, params, rest: '' }));
132+
if (matches) return (pr = cloneElement(vnode, m));
133+
if (vnode.props.default) d = cloneElement(vnode, m);
134+
});
135+
cur.current = h(RouteContext.Provider, { value: m }, pr || d);
136+
139137
// Reset previous children - if rendering succeeds synchronously, we shouldn't render the previous children.
140138
const p = prev.current;
141139
prev.current = null;

test/router.test.js

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import { jest, describe, it, beforeEach, expect } from '@jest/globals';
22
import { h, render } from 'preact';
3+
import { useState } from 'preact/hooks';
34
import { html } from 'htm/preact';
45
import { LocationProvider, Router, useLocation, Route, useRoute } from '../src/router.js';
56
import lazy, { ErrorBoundary } from '../src/lazy.js';
@@ -55,6 +56,56 @@ describe('Router', () => {
5556
});
5657
});
5758

59+
it('should allow updating props in a route', async () => {
60+
const Home = jest.fn(() => html`<h1>Home</h1>`);
61+
const stack = [];
62+
let loc, set;
63+
64+
const App = () => {
65+
const [test, setTest] = useState('2');
66+
set = setTest;
67+
return html`
68+
<${LocationProvider}>
69+
<${Router}
70+
onRouteChange=${url => {
71+
stack.push(url);
72+
}}
73+
>
74+
<${Home} path="/" test=${test} />
75+
<//>
76+
<${() => {
77+
loc = useLocation();
78+
}} />
79+
<//>
80+
`;
81+
}
82+
render(
83+
html`<${App} />`,
84+
scratch
85+
);
86+
87+
expect(scratch).toHaveProperty('textContent', 'Home');
88+
expect(Home).toHaveBeenCalledWith({ path: '/', query: {}, params: {}, rest: '', test: '2' }, expect.anything());
89+
expect(loc).toMatchObject({
90+
url: '/',
91+
path: '/',
92+
query: {},
93+
route: expect.any(Function)
94+
});
95+
96+
set('3')
97+
await sleep(1);
98+
99+
expect(Home).toHaveBeenCalledWith({ path: '/', query: {}, params: {}, rest: '', test: '3' }, expect.anything());
100+
expect(loc).toMatchObject({
101+
url: '/',
102+
path: '/',
103+
query: {},
104+
route: expect.any(Function)
105+
});
106+
expect(scratch).toHaveProperty('textContent', 'Home');
107+
});
108+
58109
it('should switch between synchronous routes', async () => {
59110
const Home = jest.fn(() => html`<h1>Home</h1>`);
60111
const Profiles = jest.fn(() => html`<h1>Profiles</h1>`);

0 commit comments

Comments
 (0)