blob: 745c22deec1821353f474d94960f0fd154a28464 (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
|
module DOM = Webapi.Dom;
module Location = DOM.Location;
module History = DOM.History;
module ReadableStream = Webapi.ReadableStream;
[@mel.scope "window"] [@mel.set]
external setNavigate: (Webapi.Dom.Window.t, string => unit) => unit =
"__navigate";
[@mel.module "react"]
external startTransition: (unit => unit) => unit = "startTransition";
external readable_stream: ReadableStream.t =
"window.srr_stream.readable_stream";
let fetchApp = url => {
let headers =
Fetch.HeadersInit.make({"Accept": "application/react.component"});
Fetch.fetchWithInit(
url,
Fetch.RequestInit.make(~method=Fetch.Get, ~headers, ()),
);
};
module App = {
let initialData =
ReactServerDOMEsbuild.createFromReadableStream(readable_stream);
[@react.component]
let make = () => {
let initialElement = React.Experimental.use(initialData);
let (data, setData) = React.Uncurried.useState(() => initialElement);
let navigate = search => {
let location = DOM.window->DOM.Window.location;
let currentSearch = Location.search(location);
if (currentSearch == "?" ++ search) {
();
} else {
let origin = Location.origin(location);
let pathname = Location.pathname(location);
let currentURL = origin ++ pathname;
let url = URL.makeExn(currentURL)->URL.setSearchAsString(search);
let app = fetchApp(URL.toString(url));
let element = ReactServerDOMEsbuild.createFromFetch(app);
startTransition(() => {
setData(. _ => element);
History.pushState(
History.state(DOM.history),
"",
URL.toString(url),
DOM.history,
);
});
();
};
};
/* Publish navigate fn into window.__navigate */
setNavigate(Webapi.Dom.window, navigate);
<ReasonReactErrorBoundary
fallback={error => {
Js.log(error);
<h1> {React.string("Something went wrong")} </h1>;
}}>
data
</ReasonReactErrorBoundary>;
};
};
let document: option(Webapi.Dom.Element.t) = [%mel.raw "window.document"];
let body =
Webapi.Dom.document
->Webapi.Dom.Document.asHtmlDocument
->Option.bind(Webapi.Dom.HtmlDocument.body);
switch (document) {
| Some(element) =>
startTransition(() => {
let _ = ReactDOM.Client.hydrateRoot(element, <App />);
();
})
| None => Js.log("Root element not found")
};
|