Skip to content

Commit 72903a9

Browse files
committed
packageEdit: don't load data on SSR loader
The page requires authentication and authorization, and the SSR rendering half a form that's shown to user while the client side checks for permissions is just bad UX. Instead, return undefined so the component renders immediately and show a skeleton component to user.
1 parent 972a9ae commit 72903a9

File tree

2 files changed

+20
-40
lines changed

2 files changed

+20
-40
lines changed

apps/cyberstorm-remix/app/p/packageEdit.css

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,4 +85,8 @@
8585
.package-edit__save-button {
8686
flex: 1 0 0;
8787
}
88+
89+
.package-edit__skeleton {
90+
min-height: 20rem;
91+
}
8892
}

apps/cyberstorm-remix/app/p/packageEdit.tsx

Lines changed: 16 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import {
66
NewIcon,
77
NewSelectSearch,
88
NewTag,
9+
SkeletonBox,
910
formatToDisplayName,
1011
useToast,
1112
} from "@thunderstore/cyberstorm";
@@ -19,18 +20,15 @@ import {
1920
} from "@thunderstore/thunderstore-api";
2021
import { DapperTs } from "@thunderstore/dapper-ts";
2122
import { type OutletContextShape } from "~/root";
22-
import {
23-
getPublicEnvVariables,
24-
getSessionTools,
25-
} from "cyberstorm/security/publicEnvVariables";
23+
import { getSessionTools } from "cyberstorm/security/publicEnvVariables";
2624
import { PageHeader } from "~/commonComponents/PageHeader/PageHeader";
2725
import { useStrongForm } from "cyberstorm/utils/StrongForm/useStrongForm";
2826
import { useReducer } from "react";
2927
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
3028
import { faBan, faCheck } from "@fortawesome/pro-solid-svg-icons";
3129
import { ApiAction } from "@thunderstore/ts-api-react-actions";
3230

33-
export const meta: MetaFunction<typeof loader> = ({ data }) => {
31+
export const meta: MetaFunction<typeof clientLoader> = ({ data }) => {
3432
return [
3533
{
3634
title: data
@@ -43,32 +41,7 @@ export const meta: MetaFunction<typeof loader> = ({ data }) => {
4341
const package404 = new Response("Package not found", { status: 404 });
4442

4543
export async function loader({ params }: LoaderFunctionArgs) {
46-
const { communityId, namespaceId, packageId } = params;
47-
48-
if (!communityId || !namespaceId || !packageId) {
49-
throw package404;
50-
}
51-
52-
try {
53-
const publicEnvVariables = getPublicEnvVariables(["VITE_API_URL"]);
54-
const dapper = new DapperTs(() => {
55-
return {
56-
apiHost: publicEnvVariables.VITE_API_URL,
57-
sessionId: undefined,
58-
};
59-
});
60-
return {
61-
listing: await dapper.getPackageListingDetails(
62-
communityId,
63-
namespaceId,
64-
packageId
65-
),
66-
filters: await dapper.getCommunityFilters(communityId),
67-
permissions: undefined,
68-
};
69-
} catch (error) {
70-
throw error instanceof ApiError ? package404 : error;
71-
}
44+
return undefined;
7245
}
7346

7447
// TODO: Needs to check if package is available for the logged in user
@@ -120,10 +93,7 @@ export async function clientLoader({ params }: LoaderFunctionArgs) {
12093
clientLoader.hydrate = true;
12194

12295
export default function PackageListing() {
123-
const { listing, filters, permissions } = useLoaderData<
124-
typeof loader | typeof clientLoader
125-
>();
126-
96+
const loaderData = useLoaderData<typeof loader | typeof clientLoader>();
12797
const outletContext = useOutletContext() as OutletContextShape;
12898
const config = outletContext.requestConfig;
12999
const toast = useToast();
@@ -183,7 +153,7 @@ export default function PackageListing() {
183153
}
184154

185155
const [formInputs, updateFormFieldState] = useReducer(formFieldUpdateAction, {
186-
categories: listing.categories.map((c) => c.slug),
156+
categories: loaderData?.listing.categories.map((c) => c.slug) ?? [],
187157
});
188158

189159
type SubmitorOutput = Awaited<ReturnType<typeof packageListingUpdate>>;
@@ -231,14 +201,20 @@ export default function PackageListing() {
231201
},
232202
});
233203

204+
if (!loaderData) {
205+
return <SkeletonBox className="package-edit__skeleton" />;
206+
}
207+
208+
const { listing, filters, permissions } = loaderData;
209+
234210
return (
235211
<>
236212
<PageHeader headingLevel="1" headingSize="2">
237213
Edit package
238214
</PageHeader>
239215
<div className="package-edit__main">
240216
<section className="package-edit__section">
241-
{permissions?.permissions.can_unlist ? (
217+
{permissions.permissions.can_unlist && (
242218
<>
243219
<div className="package-edit__row">
244220
<div className="package-edit__info">
@@ -278,8 +254,8 @@ export default function PackageListing() {
278254
</div>
279255
<div className="package-edit__divider" />
280256
</>
281-
) : null}
282-
{permissions?.permissions.can_manage_deprecation ? (
257+
)}
258+
{permissions.permissions.can_manage_deprecation && (
283259
<>
284260
<div className="package-edit__row">
285261
<div className="package-edit__info">
@@ -329,7 +305,7 @@ export default function PackageListing() {
329305
</div>
330306
<div className="package-edit__divider" />
331307
</>
332-
) : null}
308+
)}
333309
<div className="package-edit__row">
334310
<div className="package-edit__info">
335311
<div className="package-edit__title">Categories</div>

0 commit comments

Comments
 (0)