Merge pull request #178 from trails-cool/fix/leaflet-ssr
Fix Leaflet SSR error: use .client.tsx convention
This commit is contained in:
commit
12fde4aa20
6 changed files with 30 additions and 32 deletions
21
apps/journal/app/components/ClientMap.tsx
Normal file
21
apps/journal/app/components/ClientMap.tsx
Normal file
|
|
@ -0,0 +1,21 @@
|
||||||
|
import { useState, useEffect, type ComponentProps } from "react";
|
||||||
|
|
||||||
|
type MapProps = ComponentProps<typeof import("./RouteMapThumbnail.client").RouteMapThumbnail>;
|
||||||
|
|
||||||
|
export function ClientMap(props: MapProps) {
|
||||||
|
const [Component, setComponent] = useState<React.ComponentType<MapProps>>();
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
import("./RouteMapThumbnail.client").then((m) => setComponent(() => m.RouteMapThumbnail));
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
if (!Component) {
|
||||||
|
return (
|
||||||
|
<div className={`flex items-center justify-center bg-gray-100 text-gray-500 ${props.className ?? "h-36 w-full rounded"}`}>
|
||||||
|
Loading map...
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return <Component {...props} />;
|
||||||
|
}
|
||||||
|
|
@ -1,4 +1,3 @@
|
||||||
import { Suspense, lazy } from "react";
|
|
||||||
import { data, redirect } from "react-router";
|
import { data, redirect } from "react-router";
|
||||||
import { useTranslation } from "react-i18next";
|
import { useTranslation } from "react-i18next";
|
||||||
import type { Route } from "./+types/activities.$id";
|
import type { Route } from "./+types/activities.$id";
|
||||||
|
|
@ -7,10 +6,7 @@ import { getActivity, deleteActivity, linkActivityToRoute, createRouteFromActivi
|
||||||
import { deleteImportByActivity } from "~/lib/sync/imports.server";
|
import { deleteImportByActivity } from "~/lib/sync/imports.server";
|
||||||
import { listRoutes } from "~/lib/routes.server";
|
import { listRoutes } from "~/lib/routes.server";
|
||||||
import { ClientDate } from "~/components/ClientDate";
|
import { ClientDate } from "~/components/ClientDate";
|
||||||
|
import { ClientMap } from "~/components/ClientMap";
|
||||||
const RouteMapThumbnail = lazy(() =>
|
|
||||||
import("~/components/RouteMapThumbnail").then((m) => ({ default: m.RouteMapThumbnail })),
|
|
||||||
);
|
|
||||||
|
|
||||||
export async function loader({ params, request }: Route.LoaderArgs) {
|
export async function loader({ params, request }: Route.LoaderArgs) {
|
||||||
const activity = await getActivity(params.id);
|
const activity = await getActivity(params.id);
|
||||||
|
|
@ -125,9 +121,7 @@ export default function ActivityDetailPage({ loaderData }: Route.ComponentProps)
|
||||||
|
|
||||||
{activity.geojson && (
|
{activity.geojson && (
|
||||||
<div className="mt-6 overflow-hidden rounded-lg border border-gray-200" style={{ height: 400 }}>
|
<div className="mt-6 overflow-hidden rounded-lg border border-gray-200" style={{ height: 400 }}>
|
||||||
<Suspense fallback={<div className="flex h-full items-center justify-center bg-gray-100 text-gray-500">Loading map...</div>}>
|
<ClientMap geojson={activity.geojson} interactive className="h-full w-full" />
|
||||||
<RouteMapThumbnail geojson={activity.geojson} interactive className="h-full w-full" />
|
|
||||||
</Suspense>
|
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,14 +1,10 @@
|
||||||
import { data, redirect } from "react-router";
|
import { data, redirect } from "react-router";
|
||||||
import { Suspense, lazy } from "react";
|
|
||||||
import { useTranslation } from "react-i18next";
|
import { useTranslation } from "react-i18next";
|
||||||
import type { Route } from "./+types/activities._index";
|
import type { Route } from "./+types/activities._index";
|
||||||
import { getSessionUser } from "~/lib/auth.server";
|
import { getSessionUser } from "~/lib/auth.server";
|
||||||
import { listActivities } from "~/lib/activities.server";
|
import { listActivities } from "~/lib/activities.server";
|
||||||
import { ClientDate } from "~/components/ClientDate";
|
import { ClientDate } from "~/components/ClientDate";
|
||||||
|
import { ClientMap } from "~/components/ClientMap";
|
||||||
const RouteMapThumbnail = lazy(() =>
|
|
||||||
import("~/components/RouteMapThumbnail").then((m) => ({ default: m.RouteMapThumbnail })),
|
|
||||||
);
|
|
||||||
|
|
||||||
export async function loader({ request }: Route.LoaderArgs) {
|
export async function loader({ request }: Route.LoaderArgs) {
|
||||||
const user = await getSessionUser(request);
|
const user = await getSessionUser(request);
|
||||||
|
|
@ -64,9 +60,7 @@ export default function ActivitiesListPage({ loaderData }: Route.ComponentProps)
|
||||||
<div className="flex gap-4">
|
<div className="flex gap-4">
|
||||||
<div className="w-48 shrink-0">
|
<div className="w-48 shrink-0">
|
||||||
{activity.geojson ? (
|
{activity.geojson ? (
|
||||||
<Suspense fallback={<div className="h-36 w-full animate-pulse rounded bg-gray-100" />}>
|
<ClientMap geojson={activity.geojson} />
|
||||||
<RouteMapThumbnail geojson={activity.geojson} />
|
|
||||||
</Suspense>
|
|
||||||
) : (
|
) : (
|
||||||
<div className="flex h-36 w-full items-center justify-center rounded bg-gray-100 text-xs text-gray-400">
|
<div className="flex h-36 w-full items-center justify-center rounded bg-gray-100 text-xs text-gray-400">
|
||||||
{t("routes.noMapPreview")}
|
{t("routes.noMapPreview")}
|
||||||
|
|
|
||||||
|
|
@ -1,14 +1,11 @@
|
||||||
import { useState, useCallback, Suspense, lazy } from "react";
|
import { useState, useCallback } from "react";
|
||||||
import { data, redirect } from "react-router";
|
import { data, redirect } from "react-router";
|
||||||
import { useTranslation } from "react-i18next";
|
import { useTranslation } from "react-i18next";
|
||||||
import type { Route } from "./+types/routes.$id";
|
import type { Route } from "./+types/routes.$id";
|
||||||
import { getSessionUser } from "~/lib/auth.server";
|
import { getSessionUser } from "~/lib/auth.server";
|
||||||
import { getRoute, getRouteWithVersions, deleteRoute, updateRoute } from "~/lib/routes.server";
|
import { getRoute, getRouteWithVersions, deleteRoute, updateRoute } from "~/lib/routes.server";
|
||||||
import { ClientDate } from "~/components/ClientDate";
|
import { ClientDate } from "~/components/ClientDate";
|
||||||
|
import { ClientMap } from "~/components/ClientMap";
|
||||||
const RouteMapThumbnail = lazy(() =>
|
|
||||||
import("~/components/RouteMapThumbnail").then((m) => ({ default: m.RouteMapThumbnail })),
|
|
||||||
);
|
|
||||||
|
|
||||||
|
|
||||||
export async function loader({ params, request }: Route.LoaderArgs) {
|
export async function loader({ params, request }: Route.LoaderArgs) {
|
||||||
|
|
@ -161,9 +158,7 @@ export default function RouteDetailPage({ loaderData }: Route.ComponentProps) {
|
||||||
|
|
||||||
{route.geojson && (
|
{route.geojson && (
|
||||||
<div className="mt-6 overflow-hidden rounded-lg border border-gray-200" style={{ height: 400 }}>
|
<div className="mt-6 overflow-hidden rounded-lg border border-gray-200" style={{ height: 400 }}>
|
||||||
<Suspense fallback={<div className="flex h-full items-center justify-center bg-gray-100 text-gray-500">Loading map...</div>}>
|
<ClientMap geojson={route.geojson} interactive className="h-full w-full" />
|
||||||
<RouteMapThumbnail geojson={route.geojson} interactive className="h-full w-full" />
|
|
||||||
</Suspense>
|
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,14 +1,10 @@
|
||||||
import { data, redirect } from "react-router";
|
import { data, redirect } from "react-router";
|
||||||
import { Suspense, lazy } from "react";
|
|
||||||
import { useTranslation } from "react-i18next";
|
import { useTranslation } from "react-i18next";
|
||||||
import type { Route } from "./+types/routes._index";
|
import type { Route } from "./+types/routes._index";
|
||||||
import { getSessionUser } from "~/lib/auth.server";
|
import { getSessionUser } from "~/lib/auth.server";
|
||||||
import { listRoutes } from "~/lib/routes.server";
|
import { listRoutes } from "~/lib/routes.server";
|
||||||
import { ClientDate } from "~/components/ClientDate";
|
import { ClientDate } from "~/components/ClientDate";
|
||||||
|
import { ClientMap } from "~/components/ClientMap";
|
||||||
const RouteMapThumbnail = lazy(() =>
|
|
||||||
import("~/components/RouteMapThumbnail").then((m) => ({ default: m.RouteMapThumbnail })),
|
|
||||||
);
|
|
||||||
|
|
||||||
export async function loader({ request }: Route.LoaderArgs) {
|
export async function loader({ request }: Route.LoaderArgs) {
|
||||||
const user = await getSessionUser(request);
|
const user = await getSessionUser(request);
|
||||||
|
|
@ -62,9 +58,7 @@ export default function RoutesListPage({ loaderData }: Route.ComponentProps) {
|
||||||
<div className="flex gap-4">
|
<div className="flex gap-4">
|
||||||
<div className="w-48 shrink-0">
|
<div className="w-48 shrink-0">
|
||||||
{route.geojson ? (
|
{route.geojson ? (
|
||||||
<Suspense fallback={<div className="h-36 w-full animate-pulse rounded bg-gray-100" />}>
|
<ClientMap geojson={route.geojson} />
|
||||||
<RouteMapThumbnail geojson={route.geojson} />
|
|
||||||
</Suspense>
|
|
||||||
) : (
|
) : (
|
||||||
<div className="flex h-36 w-full items-center justify-center rounded bg-gray-100 text-xs text-gray-400">
|
<div className="flex h-36 w-full items-center justify-center rounded bg-gray-100 text-xs text-gray-400">
|
||||||
{t("routes.noMapPreview")}
|
{t("routes.noMapPreview")}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue