Skip to content

Commit 4d124a4

Browse files
authored
[Blocks Fixture] Misc updates (facebook#18811)
* [Blocks Fixture] Update navigation buttons immediately * Add more profile links * Minor refactor * Add subroutes to Profile
1 parent fe7163e commit 4d124a4

File tree

13 files changed

+224
-84
lines changed

13 files changed

+224
-84
lines changed

fixtures/blocks/db.json

Lines changed: 26 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -23,37 +23,55 @@
2323
{
2424
"id": 1,
2525
"body": "Hey there",
26-
"postId": 1
26+
"postId": 1,
27+
"userId": 1
2728
},
2829
{
2930
"id": 2,
3031
"body": "Welcome to the chat",
31-
"postId": 1
32+
"postId": 1,
33+
"userId": 2
3234
},
3335
{
3436
"id": 3,
3537
"body": "What editor/font are you using?",
36-
"postId": 2
38+
"postId": 2,
39+
"userId": 2
3740
},
3841
{
3942
"id": 4,
4043
"body": "It's always been hard",
41-
"postId": 3
44+
"postId": 3,
45+
"userId": 1
4246
},
4347
{
4448
"id": 5,
4549
"body": "It's still easy",
46-
"postId": 3
50+
"postId": 3,
51+
"userId": 2
4752
}
4853
],
4954
"users": [{
5055
"id": 1,
51-
"name": "Sebastian"
56+
"name": "Sebastian",
57+
"bioId": 10
5258
}, {
5359
"id": 2,
54-
"name": "Sophie"
60+
"name": "Sophie",
61+
"bioId": 20
5562
}, {
5663
"id": 3,
57-
"name": "Dan"
64+
"name": "Dan",
65+
"bioId": 30
66+
}],
67+
"bios": [{
68+
"id": 10,
69+
"text": "I like European movies"
70+
}, {
71+
"id": 20,
72+
"text": "I like math puzzles"
73+
}, {
74+
"id": 30,
75+
"text": "I like reading twitter"
5876
}]
5977
}

fixtures/blocks/src/Router.js

Lines changed: 19 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -24,17 +24,24 @@ const initialState = {
2424
// TODO: use this for invalidation.
2525
cache: createCache(),
2626
url: initialUrl,
27+
pendingUrl: initialUrl,
2728
RootBlock: loadApp(initialUrl),
2829
};
2930

3031
function reducer(state, action) {
3132
switch (action.type) {
32-
case 'navigate':
33+
case 'startNavigation':
34+
return {
35+
...state,
36+
pendingUrl: action.url,
37+
};
38+
case 'completeNavigation':
3339
// TODO: cancel previous fetch?
3440
return {
35-
cache: state.cache,
41+
...state,
3642
url: action.url,
37-
RootBlock: loadApp(action.url),
43+
pendingUrl: action.url,
44+
RootBlock: action.RootBlock,
3845
};
3946
default:
4047
throw new Error();
@@ -44,7 +51,7 @@ function reducer(state, action) {
4451
function Router() {
4552
const [state, dispatch] = useReducer(reducer, initialState);
4653
const [startTransition, isPending] = useTransition({
47-
timeoutMs: 3000,
54+
timeoutMs: 1500,
4855
});
4956

5057
useEffect(() => {
@@ -56,12 +63,16 @@ function Router() {
5663
startTransition(() => {
5764
// TODO: Here, There, and Everywhere.
5865
// TODO: Instant Transitions, somehow.
59-
// TODO: Buttons should update immediately.
6066
dispatch({
61-
type: 'navigate',
67+
type: 'completeNavigation',
68+
RootBlock: loadApp(url),
6269
url,
6370
});
6471
});
72+
dispatch({
73+
type: 'startNavigation',
74+
url,
75+
});
6576
},
6677
[startTransition]
6778
);
@@ -76,10 +87,11 @@ function Router() {
7687

7788
const routeContext = useMemo(
7889
() => ({
90+
pendingUrl: state.pendingUrl,
7991
url: state.url,
8092
navigate,
8193
}),
82-
[state.url, navigate]
94+
[state.url, state.pendingUrl, navigate]
8395
);
8496

8597
return (

fixtures/blocks/src/client/Link.js

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
/**
2+
* Copyright (c) Facebook, Inc. and its affiliates.
3+
*
4+
* This source code is licensed under the MIT license found in the
5+
* LICENSE file in the root directory of this source tree.
6+
*/
7+
8+
import * as React from 'react';
9+
import {useRouter} from './RouterContext';
10+
11+
export default function Link({to, children, ...rest}) {
12+
const {navigate} = useRouter();
13+
return (
14+
<a
15+
href={to}
16+
onClick={e => {
17+
e.preventDefault();
18+
window.history.pushState(null, null, to);
19+
navigate(to);
20+
}}
21+
{...rest}>
22+
{children}
23+
</a>
24+
);
25+
}

fixtures/blocks/src/client/Shell.js

Lines changed: 10 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -6,57 +6,25 @@
66
*/
77

88
import * as React from 'react';
9-
import {useRouter} from './RouterContext';
9+
import {TabBar, TabLink} from './TabNav';
1010

11-
function TabBar({children}) {
12-
return (
13-
<div style={{border: '1px solid #aaa', padding: 20, width: 500}}>
14-
{children}
15-
</div>
16-
);
17-
}
11+
// TODO: Error Boundaries.
1812

19-
function TabLink({to, children}) {
20-
const {url: activeUrl, navigate} = useRouter();
21-
const active = activeUrl === to;
22-
if (active) {
23-
return (
24-
<b
25-
style={{
26-
display: 'inline-block',
27-
width: 50,
28-
marginRight: 20,
29-
}}>
30-
{children}
31-
</b>
32-
);
33-
}
13+
function MainTabNav() {
3414
return (
35-
<a
36-
style={{
37-
display: 'inline-block',
38-
width: 50,
39-
marginRight: 20,
40-
}}
41-
href={to}
42-
onClick={e => {
43-
e.preventDefault();
44-
window.history.pushState(null, null, to);
45-
navigate(to);
46-
}}>
47-
{children}
48-
</a>
15+
<TabBar>
16+
<TabLink to="/">Home</TabLink>
17+
<TabLink to="/profile/3" partial={true}>
18+
Profile
19+
</TabLink>
20+
</TabBar>
4921
);
5022
}
5123

5224
export default function Shell({children}) {
5325
return (
5426
<>
55-
<TabBar>
56-
<TabLink to="/">Home</TabLink>
57-
<TabLink to="/profile">Profile</TabLink>
58-
</TabBar>
59-
<br />
27+
<MainTabNav />
6028
{children}
6129
</>
6230
);

fixtures/blocks/src/client/TabNav.js

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
/**
2+
* Copyright (c) Facebook, Inc. and its affiliates.
3+
*
4+
* This source code is licensed under the MIT license found in the
5+
* LICENSE file in the root directory of this source tree.
6+
*/
7+
8+
import * as React from 'react';
9+
import Link from './Link';
10+
import {useRouter} from './RouterContext';
11+
12+
export function TabBar({children}) {
13+
return (
14+
<div
15+
style={{
16+
border: '1px solid #aaa',
17+
padding: 20,
18+
marginBottom: 20,
19+
width: 500,
20+
}}>
21+
{children}
22+
</div>
23+
);
24+
}
25+
26+
export function TabLink({to, partial, children}) {
27+
const {pendingUrl: activeUrl} = useRouter();
28+
const active = partial ? activeUrl.startsWith(to) : activeUrl === to;
29+
if (active) {
30+
return (
31+
<b
32+
style={{
33+
display: 'inline-block',
34+
marginRight: 20,
35+
}}>
36+
{children}
37+
</b>
38+
);
39+
}
40+
return (
41+
<Link
42+
style={{
43+
display: 'inline-block',
44+
marginRight: 20,
45+
}}
46+
to={to}>
47+
{children}
48+
</Link>
49+
);
50+
}

fixtures/blocks/src/server/App.block.js

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -16,15 +16,13 @@ import loadProfilePage from './ProfilePage.block';
1616

1717
function load(url) {
1818
let Page;
19-
switch (url) {
20-
case '/':
21-
Page = loadFeedPage();
22-
break;
23-
case '/profile':
24-
Page = loadProfilePage(3);
25-
break;
26-
default:
27-
throw Error('Not found');
19+
const segments = url.split('/').filter(Boolean);
20+
if (segments.length === 0) {
21+
Page = loadFeedPage();
22+
} else if (segments[0] === 'profile') {
23+
Page = loadProfilePage(Number(segments[1]), segments[2]);
24+
} else {
25+
throw Error('Not found');
2826
}
2927
return {Page};
3028
}
@@ -33,6 +31,8 @@ function load(url) {
3331

3432
import Shell from '../client/Shell';
3533

34+
// TODO: some notion of key.
35+
3636
function App(props, data) {
3737
return (
3838
<Shell>

fixtures/blocks/src/server/Comments.block.js

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,19 +15,25 @@ import {fetch} from 'react-data/fetch';
1515

1616
function load(postId) {
1717
return {
18-
comments: fetch(`/comments?postId=${postId}`).json(),
18+
comments: fetch(`/comments?postId=${postId}&_expand=user`).json(),
1919
};
2020
}
2121

2222
// Client
2323

24+
import Link from '../client/Link';
25+
2426
function Comments(props, data) {
2527
return (
2628
<>
2729
<h5>Comments</h5>
2830
<ul>
29-
{data.comments.slice(0, 5).map(item => (
30-
<li key={item.id}>{item.body}</li>
31+
{data.comments.slice(0, 5).map(comment => (
32+
<li key={comment.id}>
33+
{comment.body}
34+
{' • '}
35+
<Link to={`/profile/${comment.user.id}`}>{comment.user.name}</Link>
36+
</li>
3137
))}
3238
</ul>
3339
</>

fixtures/blocks/src/server/FeedPage.block.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ import {fetch} from 'react-data/fetch';
1515
import PostList from './PostList';
1616

1717
function load(params) {
18-
const allPosts = fetch('/posts').json();
18+
const allPosts = fetch('/posts?_expand=user').json();
1919
return {
2020
posts: <PostList posts={allPosts} />,
2121
};

fixtures/blocks/src/server/Post.block.js

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@ function load(postId) {
2121

2222
// Client
2323

24+
import Link from '../client/Link';
25+
2426
function Post(props, data) {
2527
return (
2628
<div
@@ -31,7 +33,13 @@ function Post(props, data) {
3133
padding: 20,
3234
maxWidth: 500,
3335
}}>
34-
<h4 style={{marginTop: 0}}>{props.post.title}</h4>
36+
<h4 style={{marginTop: 0}}>
37+
{props.post.title}
38+
{' by '}
39+
<Link to={`/profile/${props.post.user.id}`}>
40+
{props.post.user.name}
41+
</Link>
42+
</h4>
3543
<p>{props.post.body}</p>
3644
<Suspense
3745
fallback={<h5>Loading comments...</h5>}

fixtures/blocks/src/server/PostList.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ export default function PostList({posts}) {
1717
return (
1818
<SuspenseList revealOrder="forwards" tail="collapsed">
1919
{posts.map(post => {
20-
preload(`/comments?postId=${post.id}`);
20+
preload(`/comments?postId=${post.id}&_expand=user`);
2121
const Post = loadPost(post.id);
2222
return (
2323
<Suspense key={post.id} fallback={<PostGlimmer />}>

0 commit comments

Comments
 (0)