-
Notifications
You must be signed in to change notification settings - Fork 2.6k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Co-authored-by: Jacob Ebey <jacob.ebey@live.com>
- Loading branch information
1 parent
39cedae
commit b790d75
Showing
15 changed files
with
744 additions
and
361 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,64 +1,61 @@ | ||
import type { BrowserHistory, Action, Location } from "@remix-run/router"; | ||
import { createBrowserHistory } from "@remix-run/router"; | ||
import type { HydrationState, Router } from "@remix-run/router"; | ||
import type { ReactElement } from "react"; | ||
import * as React from "react"; | ||
import { createBrowserRouter, RouterProvider } from "react-router-dom"; | ||
|
||
import { RemixEntry } from "./components"; | ||
import type { EntryContext } from "./entry"; | ||
import { RemixContext } from "./components"; | ||
import type { EntryContext, FutureConfig } from "./entry"; | ||
import { deserializeErrors } from "./errors"; | ||
import type { RouteModules } from "./routeModules"; | ||
import { createClientRoutes } from "./routes"; | ||
|
||
/* eslint-disable prefer-let/prefer-let */ | ||
declare global { | ||
var __remixContext: EntryContext; | ||
var __remixContext: { | ||
state: HydrationState; | ||
future: FutureConfig; | ||
}; | ||
var __remixRouteModules: RouteModules; | ||
var __remixManifest: EntryContext["manifest"]; | ||
} | ||
/* eslint-enable prefer-let/prefer-let */ | ||
|
||
export interface RemixBrowserProps {} | ||
|
||
interface Update { | ||
action: Action; | ||
location: Location; | ||
} | ||
let router: Router; | ||
|
||
/** | ||
* The entry point for a Remix app when it is rendered in the browser (in | ||
* `app/entry.client.js`). This component is used by React to hydrate the HTML | ||
* that was received from the server. | ||
*/ | ||
export function RemixBrowser(_props: RemixBrowserProps): ReactElement { | ||
let historyRef = React.useRef<BrowserHistory>(); | ||
if (historyRef.current == null) { | ||
historyRef.current = createBrowserHistory({ window, v5Compat: true }); | ||
} | ||
|
||
let history = historyRef.current; | ||
let [state, dispatch] = React.useReducer( | ||
(_: Update, update: Update) => update, | ||
{ | ||
action: history.action, | ||
location: history.location, | ||
if (!router) { | ||
let routes = createClientRoutes( | ||
window.__remixManifest.routes, | ||
window.__remixRouteModules | ||
); | ||
|
||
let hydrationData = window.__remixContext.state; | ||
if (hydrationData && hydrationData.errors) { | ||
hydrationData = { | ||
...hydrationData, | ||
errors: deserializeErrors(hydrationData.errors), | ||
}; | ||
} | ||
); | ||
|
||
React.useLayoutEffect(() => history.listen(dispatch), [history]); | ||
|
||
let entryContext = window.__remixContext; | ||
entryContext.manifest = window.__remixManifest; | ||
entryContext.routeModules = window.__remixRouteModules; | ||
// In the browser, we don't need this because a) in the case of loader | ||
// errors we already know the order and b) in the case of render errors | ||
// React knows the order and handles error boundaries normally. | ||
entryContext.appState.trackBoundaries = false; | ||
entryContext.appState.trackCatchBoundaries = false; | ||
router = createBrowserRouter(routes, { hydrationData }); | ||
} | ||
|
||
return ( | ||
<RemixEntry | ||
context={entryContext} | ||
action={state.action} | ||
location={state.location} | ||
navigator={history} | ||
/> | ||
<RemixContext.Provider | ||
value={{ | ||
manifest: window.__remixManifest, | ||
routeModules: window.__remixRouteModules, | ||
future: window.__remixContext.future, | ||
}} | ||
> | ||
<RouterProvider router={router} fallbackElement={null} /> | ||
</RemixContext.Provider> | ||
); | ||
} |
Oops, something went wrong.