summaryrefslogtreecommitdiff
path: root/preact/demo/suspense-router
diff options
context:
space:
mode:
Diffstat (limited to 'preact/demo/suspense-router')
-rw-r--r--preact/demo/suspense-router/bye.js12
-rw-r--r--preact/demo/suspense-router/hello.js12
-rw-r--r--preact/demo/suspense-router/index.js30
-rw-r--r--preact/demo/suspense-router/simple-router.js87
4 files changed, 141 insertions, 0 deletions
diff --git a/preact/demo/suspense-router/bye.js b/preact/demo/suspense-router/bye.js
new file mode 100644
index 0000000..fe2a49c
--- /dev/null
+++ b/preact/demo/suspense-router/bye.js
@@ -0,0 +1,12 @@
+import { createElement } from 'react';
+import { Link } from './simple-router';
+
+/** @jsx createElement */
+
+export default function Bye() {
+ return (
+ <div>
+ Bye! <Link to="/">Go to Hello!</Link>
+ </div>
+ );
+}
diff --git a/preact/demo/suspense-router/hello.js b/preact/demo/suspense-router/hello.js
new file mode 100644
index 0000000..2566dd3
--- /dev/null
+++ b/preact/demo/suspense-router/hello.js
@@ -0,0 +1,12 @@
+import { createElement } from 'react';
+import { Link } from './simple-router';
+
+/** @jsx createElement */
+
+export default function Hello() {
+ return (
+ <div>
+ Hello! <Link to="/bye">Go to Bye!</Link>
+ </div>
+ );
+}
diff --git a/preact/demo/suspense-router/index.js b/preact/demo/suspense-router/index.js
new file mode 100644
index 0000000..2572209
--- /dev/null
+++ b/preact/demo/suspense-router/index.js
@@ -0,0 +1,30 @@
+import { createElement, Suspense, lazy } from 'react';
+
+import { Router, Route, Switch } from './simple-router';
+
+/** @jsx createElement */
+
+let Hello = lazy(() => import('./hello.js'));
+let Bye = lazy(() => import('./bye.js'));
+
+function Loading() {
+ return <div>Hey! This is a fallback because we're loading things! :D</div>;
+}
+
+export default function SuspenseRouterBug() {
+ return (
+ <Router>
+ <h1>Suspense Router bug</h1>
+ <Suspense fallback={<Loading />}>
+ <Switch>
+ <Route path="/" exact>
+ <Hello />
+ </Route>
+ <Route path="/bye">
+ <Bye />
+ </Route>
+ </Switch>
+ </Suspense>
+ </Router>
+ );
+}
diff --git a/preact/demo/suspense-router/simple-router.js b/preact/demo/suspense-router/simple-router.js
new file mode 100644
index 0000000..ed48ea6
--- /dev/null
+++ b/preact/demo/suspense-router/simple-router.js
@@ -0,0 +1,87 @@
+import {
+ createElement,
+ cloneElement,
+ createContext,
+ useState,
+ useContext,
+ Children,
+ useLayoutEffect
+} from 'react';
+
+/** @jsx createElement */
+
+const memoryHistory = {
+ /**
+ * @typedef {{ pathname: string }} Location
+ * @typedef {(location: Location) => void} HistoryListener
+ * @type {HistoryListener[]}
+ */
+ listeners: [],
+
+ /**
+ * @param {HistoryListener} listener
+ */
+ listen(listener) {
+ const newLength = this.listeners.push(listener);
+ return () => this.listeners.splice(newLength - 1, 1);
+ },
+
+ /**
+ * @param {Location} to
+ */
+ navigate(to) {
+ this.listeners.forEach(listener => listener(to));
+ }
+};
+
+/** @type {import('react').Context<{ history: typeof memoryHistory; location: Location }>} */
+const RouterContext = createContext(null);
+
+export function Router({ history = memoryHistory, children }) {
+ const [location, setLocation] = useState({ pathname: '/' });
+
+ useLayoutEffect(() => {
+ return history.listen(newLocation => setLocation(newLocation));
+ }, []);
+
+ return (
+ <RouterContext.Provider value={{ history, location }}>
+ {children}
+ </RouterContext.Provider>
+ );
+}
+
+export function Switch(props) {
+ const { location } = useContext(RouterContext);
+
+ let element = null;
+ Children.forEach(props.children, child => {
+ if (element == null && child.props.path == location.pathname) {
+ element = child;
+ }
+ });
+
+ return element;
+}
+
+/**
+ * @param {{ children: any; path: string; exact?: boolean; }} props
+ */
+export function Route({ children, path, exact }) {
+ return children;
+}
+
+export function Link({ to, children }) {
+ const { history } = useContext(RouterContext);
+ const onClick = event => {
+ event.preventDefault();
+ event.stopPropagation();
+ history.navigate({ pathname: to });
+ };
+
+ return (
+ <a href={to} onClick={onClick}>
+ {children}
+ </a>
+ );
+}