Skip to content

Commit 1c46097

Browse files
authored
feat: add waitBeforeTransition option on link (#3)
1 parent 153cfcf commit 1c46097

File tree

10 files changed

+161
-56
lines changed

10 files changed

+161
-56
lines changed

examples/wordpress/src/pages/index.js

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,9 @@ export default function Page({ title, book, specificBook, allBooks, blocks }) {
4646
<ul>
4747
{allBooks.map(b => (
4848
<li key={b.metadata.id}>
49-
<Link to={`/books/${b.metadata.slug}`}>{b.name}</Link>
49+
<Link waitBeforeTransition to={`/books/${b.metadata.slug}`}>
50+
{b.name}
51+
</Link>
5052
</li>
5153
))}
5254
</ul>

packages/smooth-core/src/client/ErrorBoundary.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import React from 'react'
22
import loadable from '@loadable/component'
3-
import { Status } from '../router'
3+
import { Status } from '../router/Status'
44

55
const ErrorPage = loadable(() => import('__smooth_error'))
66

Lines changed: 39 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1,38 +1,50 @@
11
import React from 'react'
22
import { Switch, Route } from 'react-router-dom'
33
import Page, { getPages } from './Page'
4+
import HiddenRouter from '../router/HiddenRouter'
5+
import { Provider as HiddenHistoryContextProvider } from '../router/HiddenHistoryContext'
46

57
const pages = getPages()
68

79
export default function Routes() {
810
return (
9-
<Route
10-
path="/:lang(.{2})?"
11-
render={({
12-
match: {
13-
url,
14-
params: { lang = null },
15-
},
16-
}) => (
17-
<Switch>
18-
{pages.map((page, index) => (
19-
<Route
20-
key={index}
21-
path={`${url}${page.routePath}`}
22-
render={({ history, match, location }) => (
23-
<Page
24-
lang={lang}
25-
indexUrl={`${url}${page.indexPath}`}
26-
page={page}
27-
history={history}
28-
match={match}
29-
location={location}
11+
<HiddenHistoryContextProvider>
12+
<Route
13+
path="/:lang(.{2})?"
14+
render={({
15+
match: {
16+
url,
17+
params: { lang = null },
18+
},
19+
}) => {
20+
const routes = (
21+
<Switch>
22+
{pages.map((page, index) => (
23+
<Route
24+
key={index}
25+
path={`${url}${page.routePath}`}
26+
render={({ history, match, location }) => (
27+
<Page
28+
lang={lang}
29+
indexUrl={`${url}${page.indexPath}`}
30+
page={page}
31+
history={history}
32+
match={match}
33+
location={location}
34+
/>
35+
)}
3036
/>
31-
)}
32-
/>
33-
))}
34-
</Switch>
35-
)}
36-
/>
37+
))}
38+
</Switch>
39+
)
40+
return (
41+
<>
42+
{routes}
43+
<HiddenRouter>{routes}</HiddenRouter>
44+
</>
45+
)
46+
}}
47+
/>
48+
</HiddenHistoryContextProvider>
3749
)
3850
}

packages/smooth-core/src/content/Query.js

Lines changed: 22 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,13 @@
1-
import React from 'react'
1+
import React, { useContext, useEffect } from 'react'
22
import camelcase from 'camelcase'
33
import gql from 'graphql-tag'
44
import qs from 'query-string'
55
import { Redirect } from 'react-router-dom'
66
import { Query as ApolloQuery } from 'react-apollo'
77
import PageContext from '../client/PageContext'
8-
import { HTTPError } from '../router'
8+
import { HTTPError } from '../router/HTTPError'
99
import { applyHook } from '../plugin/browser'
10+
import { HiddenRouterContext } from '../router/HiddenRouter'
1011
import {
1112
getFragmentDefinition,
1213
getFragment,
@@ -65,6 +66,24 @@ function getVariables(location, lang, slug = 'index') {
6566
return variables
6667
}
6768

69+
function Handler({ children, ...props }) {
70+
const hiddenRouter = useContext(HiddenRouterContext)
71+
useEffect(() => {
72+
if (hiddenRouter && !props.loading) {
73+
hiddenRouter.onPrefetched()
74+
}
75+
}, [props.loading])
76+
77+
if (!props.loading && !props.error && !props.data.contentProps) {
78+
return children({
79+
...props,
80+
error: new HTTPError({ statusCode: 404 }),
81+
})
82+
}
83+
84+
return children(props)
85+
}
86+
6887
export function Query({ children }) {
6988
return (
7089
<PageContext.Consumer>
@@ -85,20 +104,7 @@ export function Query({ children }) {
85104
query={getQuery(page)}
86105
variables={getVariables(location, lang, slug)}
87106
>
88-
{apolloProps => {
89-
if (
90-
!apolloProps.loading &&
91-
!apolloProps.error &&
92-
!apolloProps.data.contentProps
93-
) {
94-
return children({
95-
...apolloProps,
96-
error: new HTTPError({ statusCode: 404 }),
97-
})
98-
}
99-
100-
return children(apolloProps)
101-
}}
107+
{apolloProps => <Handler {...apolloProps}>{children}</Handler>}
102108
</ApolloQuery>
103109
)
104110
}}
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
import React, { createContext, useState } from 'react'
2+
3+
const HiddenHistoryContext = createContext()
4+
5+
export function Provider({ children }) {
6+
const [state, setState] = useState({ location: null, action: null })
7+
return (
8+
<HiddenHistoryContext.Provider
9+
value={{
10+
location: state.location,
11+
action: state.action,
12+
push(location) {
13+
setState({ location, action: 'PUSH' })
14+
},
15+
replace(location) {
16+
setState({ location, action: 'REPLACE' })
17+
},
18+
}}
19+
>
20+
{children}
21+
</HiddenHistoryContext.Provider>
22+
)
23+
}
24+
25+
export default HiddenHistoryContext
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
import React, { useContext, useMemo } from 'react'
2+
import { withRouter, Router } from 'react-router-dom'
3+
import HiddenHistoryContext from './HiddenHistoryContext'
4+
5+
function HiddenLinkRouter({ history, children }) {
6+
const hiddenHistory = useContext(HiddenHistoryContext)
7+
const newHistory = useMemo(() => ({ ...history }), [history])
8+
newHistory.push = hiddenHistory.push
9+
return <Router history={newHistory}>{children}</Router>
10+
}
11+
12+
export default withRouter(HiddenLinkRouter)
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
import React, { createContext, useContext } from 'react'
2+
import { StaticRouter, withRouter } from 'react-router-dom'
3+
import HiddenHistoryContext from './HiddenHistoryContext'
4+
5+
export const HiddenRouterContext = createContext()
6+
7+
function HiddenRouter({ history, children }) {
8+
const hiddenHistory = useContext(HiddenHistoryContext)
9+
return (
10+
<div style={{ display: 'none' }}>
11+
{hiddenHistory.location && (
12+
<HiddenRouterContext.Provider
13+
value={{
14+
onPrefetched: () => {
15+
switch (hiddenHistory.action) {
16+
case 'PUSH':
17+
history.push(hiddenHistory.location)
18+
break
19+
case 'REPLACE':
20+
history.replace(hiddenHistory.location)
21+
break
22+
default:
23+
return
24+
}
25+
26+
hiddenHistory.push(null)
27+
},
28+
}}
29+
>
30+
<StaticRouter context={{}} location={hiddenHistory.location}>
31+
{children}
32+
</StaticRouter>
33+
</HiddenRouterContext.Provider>
34+
)}
35+
</div>
36+
)
37+
}
38+
39+
export default withRouter(HiddenRouter)

packages/smooth-core/src/router/Link.js

Lines changed: 19 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import React from 'react'
22
import { Link as BaseLink, NavLink as BaseNavLink } from 'react-router-dom'
33
import PageContext from '../client/PageContext'
4+
import HiddenLinkRouter from './HiddenLinkRouter'
45

56
function computeTo(to, lang) {
67
if (lang) {
@@ -10,16 +11,24 @@ function computeTo(to, lang) {
1011
}
1112

1213
function createLink(Component) {
13-
return props => (
14-
<PageContext.Consumer>
15-
{pageContext => (
16-
<Component
17-
{...props}
18-
to={computeTo(props.to, pageContext ? pageContext.lang : null)}
19-
/>
20-
)}
21-
</PageContext.Consumer>
22-
)
14+
return ({ waitBeforeTransition, ...props }) => {
15+
const link = (
16+
<PageContext.Consumer>
17+
{pageContext => (
18+
<Component
19+
{...props}
20+
to={computeTo(props.to, pageContext ? pageContext.lang : null)}
21+
/>
22+
)}
23+
</PageContext.Consumer>
24+
)
25+
26+
return waitBeforeTransition ? (
27+
<HiddenLinkRouter>{link}</HiddenLinkRouter>
28+
) : (
29+
link
30+
)
31+
}
2332
}
2433

2534
export const Link = createLink(BaseLink)

packages/smooth-core/src/router/index.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,4 +11,4 @@ export {
1111
} from 'react-router-dom'
1212
export * from './Link'
1313
export * from './Status'
14-
export * from './HttpError'
14+
export * from './HTTPError'

0 commit comments

Comments
 (0)