Skip to content

Commit

Permalink
fix: experimental dehydrate/hydrate state
Browse files Browse the repository at this point in the history
  • Loading branch information
tannerlinsley committed Nov 11, 2022
1 parent a1f6b3e commit d0917c7
Show file tree
Hide file tree
Showing 10 changed files with 93 additions and 102 deletions.
1 change: 0 additions & 1 deletion examples/react/basic-ssr/server.js
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,6 @@ export async function createServer(
render = (await vite.ssrLoadModule('/src/entry-server.tsx')).render
} else {
template = indexProd
// @ts-ignore
render = (await import('./dist/server/entry-server.tsx')).render
}

Expand Down
6 changes: 5 additions & 1 deletion examples/react/basic-ssr/src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,11 @@ import { Outlet } from '@tanstack/react-router'

import { router } from './router'

console.log(router.state)

export function App() {
console.log(router.state)

return (
// Build our routes and render our router
<>
Expand All @@ -27,7 +31,7 @@ export function App() {
</router.Link>
</div>
<hr />
<Outlet /> {/* Start rendering router matches */}
<Outlet />
</>
)
}
20 changes: 7 additions & 13 deletions examples/react/basic-ssr/src/entry-client.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,23 +7,17 @@ import { App } from './App'

const state = (window as any).__TANSTACK_ROUTER_STATE__

console.log(state)

router.state = {
...router.state,
...state,
matches: router.state.matches.map((match) => {
const serverMatch = state.matches.find(
(serverMatch: any) => serverMatch.route === match.matchId,
)
Object.assign(match, serverMatch)
return match
}),
}
router.hydrateState(state)

ReactDOM.hydrateRoot(
document.getElementById('root')!,
<RouterProvider router={router}>
<App />
</RouterProvider>,
)

// ReactDOM.createRoot(document.getElementById('root')!).render(
// <RouterProvider router={router}>
// <App />
// </RouterProvider>,
// )
23 changes: 2 additions & 21 deletions examples/react/basic-ssr/src/entry-server.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,30 +17,11 @@ export async function render(url: string) {
router.mount()

await router.loadLocation()

const { status, location, matches, lastUpdated } = router.state

const payload = {
status,
location,
matches: matches.map((match) => {
const { status, routeLoaderData, loaderData, isInvalid, invalidAt } =
match

return {
status,
routeLoaderData,
loaderData,
isInvalid,
invalidAt,
}
}),
lastUpdated,
}
const routerState = router.dehydrateState()

return [
`<script>window.__TANSTACK_ROUTER_STATE__ = JSON.parse(${jsesc(
JSON.stringify(payload),
JSON.stringify(routerState),
{
isScriptContext: true,
wrap: true,
Expand Down
1 change: 0 additions & 1 deletion examples/react/basic-ssr/src/routeConfig.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,6 @@ function Posts() {
)
})}
</div>
<hr />
<Outlet />
</div>
)
Expand Down
46 changes: 13 additions & 33 deletions examples/react/basic-ssr/yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -337,11 +337,6 @@
"@jridgewell/resolve-uri" "^3.0.3"
"@jridgewell/sourcemap-codec" "^1.4.10"

"@remix-run/router@1.0.3":
version "1.0.3"
resolved "https://registry.yarnpkg.com/@remix-run/router/-/router-1.0.3.tgz#953b88c20ea00d0eddaffdc1b115c08474aa295d"
integrity sha512-ceuyTSs7PZ/tQqi19YZNBc5X7kj1f8p+4DIyrcIYFY9h+hd1OKm4RqtiWldR9eGEvIiJfsqwM4BsuCtRIuEw6Q==

"@tanstack/react-router@0.0.1-beta.3":
version "0.0.1-beta.3"
resolved "https://registry.yarnpkg.com/@tanstack/react-router/-/react-router-0.0.1-beta.3.tgz#b7fb396526fd74e6ce2b6f9e02a4dc8676018d3e"
Expand Down Expand Up @@ -1026,38 +1021,23 @@ raw-body@2.5.1:
iconv-lite "0.4.24"
unpipe "1.0.0"

react-dom@^18.2.0:
version "18.2.0"
resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-18.2.0.tgz#22aaf38708db2674ed9ada224ca4aa708d821e3d"
integrity sha512-6IMTriUmvsjHUjNtEDudZfuDQUoWXVxKHhlEGSk81n4YFS+r/Kl99wXiwlVXtPBtJenozv2P+hxDsw9eA7Xo6g==
react-dom@18.1.0:
version "18.1.0"
resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-18.1.0.tgz#7f6dd84b706408adde05e1df575b3a024d7e8a2f"
integrity sha512-fU1Txz7Budmvamp7bshe4Zi32d0ll7ect+ccxNu9FlObT605GOEB8BfO4tmRJ39R5Zj831VCpvQ05QPBW5yb+w==
dependencies:
loose-envify "^1.1.0"
scheduler "^0.23.0"
scheduler "^0.22.0"

react-refresh@^0.14.0:
version "0.14.0"
resolved "https://registry.yarnpkg.com/react-refresh/-/react-refresh-0.14.0.tgz#4e02825378a5f227079554d4284889354e5f553e"
integrity sha512-wViHqhAd8OHeLS/IRMJjTSDHF3U9eWi62F/MledQGPdJGDhodXJ9PBLNGr6WWL7qlH12Mt3TyTpbS+hGXMjCzQ==

react-router-dom@^6.4.3:
version "6.4.3"
resolved "https://registry.yarnpkg.com/react-router-dom/-/react-router-dom-6.4.3.tgz#70093b5f65f85f1df9e5d4182eb7ff3a08299275"
integrity sha512-MiaYQU8CwVCaOfJdYvt84KQNjT78VF0TJrA17SIQgNHRvLnXDJO6qsFqq8F/zzB1BWZjCFIrQpu4QxcshitziQ==
dependencies:
"@remix-run/router" "1.0.3"
react-router "6.4.3"

react-router@6.4.3:
version "6.4.3"
resolved "https://registry.yarnpkg.com/react-router/-/react-router-6.4.3.tgz#9ed3ee4d6e95889e9b075a5d63e29acc7def0d49"
integrity sha512-BT6DoGn6aV1FVP5yfODMOiieakp3z46P1Fk0RNzJMACzE7C339sFuHebfvWtnB4pzBvXXkHP2vscJzWRuUjTtA==
dependencies:
"@remix-run/router" "1.0.3"

react@^18.2.0:
version "18.2.0"
resolved "https://registry.yarnpkg.com/react/-/react-18.2.0.tgz#555bd98592883255fa00de14f1151a917b5d77d5"
integrity sha512-/3IjMdb2L9QbBdWiW5e3P2/npwMBaU9mHCSCUzNln0ZCYbcfTsGbTJrU/kGemdH2IWmB2ioZ+zkxtmq6g09fGQ==
react@18.1.0:
version "18.1.0"
resolved "https://registry.yarnpkg.com/react/-/react-18.1.0.tgz#6f8620382decb17fdc5cc223a115e2adbf104890"
integrity sha512-4oL8ivCz5ZEPyclFQXaNksK3adutVS8l2xzZU0cqEFrE9Sb7fC0EFK5uEk74wIreL1DERyjvsU915j1pcT2uEQ==
dependencies:
loose-envify "^1.1.0"

Expand Down Expand Up @@ -1097,10 +1077,10 @@ safe-buffer@5.2.1:
resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a"
integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==

scheduler@^0.23.0:
version "0.23.0"
resolved "https://registry.yarnpkg.com/scheduler/-/scheduler-0.23.0.tgz#ba8041afc3d30eb206a487b6b384002e4e61fdfe"
integrity sha512-CtuThmgHNg7zIZWAXi3AsyIzA3n4xx7aNyjwC2VJldO2LMVDhFK+63xGqq6CsJH4rTAt6/M+N4GhZiDYPx9eUw==
scheduler@^0.22.0:
version "0.22.0"
resolved "https://registry.yarnpkg.com/scheduler/-/scheduler-0.22.0.tgz#83a5d63594edf074add9a7198b1bae76c3db01b8"
integrity sha512-6QAm1BgQI88NPYymgGQLCZgvep4FyePDWFpXVK+zNSUgHwlqpJy8VEh8Et0KxTACS4VWwMousBElAZOH9nkkoQ==
dependencies:
loose-envify "^1.1.0"

Expand Down
6 changes: 0 additions & 6 deletions packages/react-router/src/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -543,12 +543,6 @@ class CatchBoundary extends React.Component<{
info,
})
}
reset = () => {
this.setState({
error: false,
info: false,
})
}
render() {
const catchElement = this.props.catchElement ?? DefaultErrorBoundary

Expand Down
66 changes: 60 additions & 6 deletions packages/router-core/src/router.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ import { defaultParseSearch, defaultStringifySearch } from './searchParams'
import {
functionalUpdate,
last,
pick,
PickAsRequired,
PickRequired,
replaceEqualDeep,
Expand Down Expand Up @@ -224,6 +225,22 @@ type LinkCurrentTargetElement = {
preloadTimeout?: null | ReturnType<typeof setTimeout>
}

interface DehydratedRouterState
extends Pick<RouterState, 'status' | 'location' | 'lastUpdated'> {
matches: DehydratedRouteMatch[]
}

interface DehydratedRouteMatch
extends Pick<
RouteMatch<any, any>,
| 'matchId'
| 'status'
| 'routeLoaderData'
| 'loaderData'
| 'isInvalid'
| 'invalidAt'
> {}

export interface Router<
TRouteConfig extends AnyRouteConfig = RouteConfig,
TAllRouteInfo extends AnyAllRouteInfo = AllRouteInfo<TRouteConfig>,
Expand Down Expand Up @@ -302,6 +319,8 @@ export interface Router<
>(
opts: LinkOptions<TAllRouteInfo, TFrom, TTo>,
) => LinkInfo
dehydrateState: () => DehydratedRouterState
hydrateState: (state: DehydratedRouterState) => void
__: {
buildRouteTree: (
routeConfig: RouteConfig,
Expand Down Expand Up @@ -396,6 +415,47 @@ export function createRouter<
router.listeners.forEach((listener) => listener(router))
},

dehydrateState: () => {
const {} = router.state

return {
...pick(router.state, ['status', 'location', 'lastUpdated']),
matches: router.state.matches.map((match) =>
pick(match, [
'matchId',
'status',
'routeLoaderData',
'loaderData',
'isInvalid',
'invalidAt',
]),
),
}
},

hydrateState: (dehydratedState) => {
// Match the routes
const matches = router.matchRoutes(router.location.pathname, {
strictParseParams: true,
})

router.state = {
...router.state,
...dehydratedState,
matches: matches.map((match) => {
const dehydratedMatch = dehydratedState.matches.find(
(d: any) => d.matchId === match.matchId,
)
invariant(
dehydratedMatch,
'Oh no! Dehydrated route matches did not match the active state of the router 😬',
)
Object.assign(match, dehydratedMatch)
return match
}),
}
},

mount: () => {
const next = router.__.buildLocation({
to: '.',
Expand Down Expand Up @@ -1019,12 +1079,6 @@ export function createRouter<
return routeConfigs.map((routeConfig) => {
const routeOptions = routeConfig.options
const route = createRoute(routeConfig, routeOptions, parent, router)

// {
// pendingMs: routeOptions.pendingMs ?? router.defaultPendingMs,
// pendingMinMs: routeOptions.pendingMinMs ?? router.defaultPendingMinMs,
// }

const existingRoute = (router.routesById as any)[route.routeId]

if (existingRoute) {
Expand Down
6 changes: 6 additions & 0 deletions packages/router-core/src/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -155,3 +155,9 @@ export function functionalUpdate<TResult>(

return updater
}

export function pick<T, K extends keyof T>(parent: T, keys: K[]): Pick<T, K> {
return keys.reduce((obj: any, key: K) => {
obj[key] = parent[key]
}, {} as any)
}
20 changes: 0 additions & 20 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -2356,11 +2356,6 @@
resolved "https://registry.yarnpkg.com/@reach/observe-rect/-/observe-rect-1.2.0.tgz#d7a6013b8aafcc64c778a0ccb83355a11204d3b2"
integrity sha512-Ba7HmkFgfQxZqqaeIWWkNK0rEhpxVQHIoVyW1YDSkGsGIXzcaW4deC8B0pZrNSSyLTdIk7y+5olKt5+g0GmFIQ==

"@remix-run/router@1.0.3":
version "1.0.3"
resolved "https://registry.yarnpkg.com/@remix-run/router/-/router-1.0.3.tgz#953b88c20ea00d0eddaffdc1b115c08474aa295d"
integrity sha512-ceuyTSs7PZ/tQqi19YZNBc5X7kj1f8p+4DIyrcIYFY9h+hd1OKm4RqtiWldR9eGEvIiJfsqwM4BsuCtRIuEw6Q==

"@rollup/plugin-babel@^5.3.1":
version "5.3.1"
resolved "https://registry.yarnpkg.com/@rollup/plugin-babel/-/plugin-babel-5.3.1.tgz#04bc0608f4aa4b2e4b1aebf284344d0f68fda283"
Expand Down Expand Up @@ -7773,21 +7768,6 @@ react-refresh@^0.14.0:
resolved "https://registry.yarnpkg.com/react-refresh/-/react-refresh-0.14.0.tgz#4e02825378a5f227079554d4284889354e5f553e"
integrity sha512-wViHqhAd8OHeLS/IRMJjTSDHF3U9eWi62F/MledQGPdJGDhodXJ9PBLNGr6WWL7qlH12Mt3TyTpbS+hGXMjCzQ==

react-router-dom@^6.4.3:
version "6.4.3"
resolved "https://registry.yarnpkg.com/react-router-dom/-/react-router-dom-6.4.3.tgz#70093b5f65f85f1df9e5d4182eb7ff3a08299275"
integrity sha512-MiaYQU8CwVCaOfJdYvt84KQNjT78VF0TJrA17SIQgNHRvLnXDJO6qsFqq8F/zzB1BWZjCFIrQpu4QxcshitziQ==
dependencies:
"@remix-run/router" "1.0.3"
react-router "6.4.3"

react-router@6.4.3:
version "6.4.3"
resolved "https://registry.yarnpkg.com/react-router/-/react-router-6.4.3.tgz#9ed3ee4d6e95889e9b075a5d63e29acc7def0d49"
integrity sha512-BT6DoGn6aV1FVP5yfODMOiieakp3z46P1Fk0RNzJMACzE7C339sFuHebfvWtnB4pzBvXXkHP2vscJzWRuUjTtA==
dependencies:
"@remix-run/router" "1.0.3"

react-virtual@^2.10.4:
version "2.10.4"
resolved "https://registry.yarnpkg.com/react-virtual/-/react-virtual-2.10.4.tgz#08712f0acd79d7d6f7c4726f05651a13b24d8704"
Expand Down

0 comments on commit d0917c7

Please sign in to comment.