-
Notifications
You must be signed in to change notification settings - Fork 4
Re-rendering performance improvements #1777
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: 04-02-refactor_replace_await_and_suspense_with_suspenseifpromise_globally
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -64,6 +64,10 @@ | |||||||||||||||||
| throw new Response("Community not found", { status: 404 }); | ||||||||||||||||||
| } | ||||||||||||||||||
|
|
||||||||||||||||||
| let cachedFilters: any = null; | ||||||||||||||||||
| let cachedCommunityId: string | null = null; | ||||||||||||||||||
| let cachedSeo: any = null; | ||||||||||||||||||
Check failureCode scanning / ESLint Disallow the `any` type Error
Unexpected any. Specify a different type.
Comment on lines
+67
to
+69
|
||||||||||||||||||
| let cachedFilters: any = null; | |
| let cachedCommunityId: string | null = null; | |
| let cachedSeo: any = null; | |
| let cachedFilters: Awaited< | |
| ReturnType<DapperTs["getCommunityFilters"]> | |
| > | null = null; | |
| let cachedCommunityId: string | null = null; | |
| let cachedSeo: ReturnType<typeof createSeo> | null = null; |
| Original file line number | Diff line number | Diff line change | ||||||||
|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -11,7 +11,14 @@ import { | |||||||||
| import { LinkLibrary } from "cyberstorm/utils/LinkLibrary"; | ||||||||||
| import { getApiHostForSsr } from "cyberstorm/utils/env"; | ||||||||||
| import { createSeo } from "cyberstorm/utils/meta"; | ||||||||||
| import { type ReactNode, memo, useEffect, useRef, useState } from "react"; | ||||||||||
| import { | ||||||||||
| type ReactNode, | ||||||||||
| memo, | ||||||||||
| useEffect, | ||||||||||
| useMemo, | ||||||||||
| useRef, | ||||||||||
| useState, | ||||||||||
| } from "react"; | ||||||||||
| import type { LinksFunction } from "react-router"; | ||||||||||
| import { | ||||||||||
| Links, | ||||||||||
|
|
@@ -261,6 +268,17 @@ export function Layout({ children }: { children: React.ReactNode }) { | |||||||||
| ? false | ||||||||||
| : true; | ||||||||||
|
|
||||||||||
| const navigationBlock = useMemo( | ||||||||||
| () => ( | ||||||||||
| <NavigationWrapper | ||||||||||
| domain={resolvedEnvVars?.VITE_API_URL || ""} | ||||||||||
| currentUser={data?.currentUser} | ||||||||||
| communityId={communityId} | ||||||||||
| /> | ||||||||||
| ), | ||||||||||
| [resolvedEnvVars?.VITE_API_URL, data?.currentUser, communityId] | ||||||||||
| ); | ||||||||||
|
|
||||||||||
| return ( | ||||||||||
| <html lang="en"> | ||||||||||
| <head> | ||||||||||
|
|
@@ -310,11 +328,7 @@ export function Layout({ children }: { children: React.ReactNode }) { | |||||||||
| <LinkingProvider value={LinkLibrary}> | ||||||||||
| <ToastProvider toastDuration={10000}> | ||||||||||
| <TooltipProvider> | ||||||||||
| <NavigationWrapper | ||||||||||
| domain={resolvedEnvVars?.VITE_API_URL || ""} | ||||||||||
| currentUser={data?.currentUser} | ||||||||||
| communityId={communityId} | ||||||||||
| /> | ||||||||||
| {navigationBlock} | ||||||||||
| <div className="container container--x container--full island"> | ||||||||||
| <main className="container container--x container--full island-item layout__main"> | ||||||||||
| <section className="container container--y container--full layout__content"> | ||||||||||
|
|
@@ -323,15 +337,7 @@ export function Layout({ children }: { children: React.ReactNode }) { | |||||||||
| {children} | ||||||||||
| </section> | ||||||||||
| </main> | ||||||||||
| {shouldShowAds ? ( | ||||||||||
| <div className="container container--y island-item layout__ads"> | ||||||||||
| <div className="container container--y layout__ads-inner"> | ||||||||||
| {adContainerIds.map((cid, k_i) => ( | ||||||||||
| <AdContainer key={k_i} containerId={cid} /> | ||||||||||
| ))} | ||||||||||
| </div> | ||||||||||
| </div> | ||||||||||
| ) : null} | ||||||||||
| <AdsColumn shouldShow={shouldShowAds} /> | ||||||||||
| </div> | ||||||||||
| <Footer /> | ||||||||||
| {shouldShowAds ? <AdsInit /> : null} | ||||||||||
|
|
@@ -352,30 +358,54 @@ const TooltipProvider = memo(function TooltipProvider({ | |||||||||
| }: { | ||||||||||
| children: ReactNode; | ||||||||||
| }) { | ||||||||||
| return <RadixTooltip delayDuration={80}>{children}</RadixTooltip>; | ||||||||||
| return ( | ||||||||||
| <RadixTooltip delayDuration={80} skipDelayDuration={200}> | ||||||||||
| {children} | ||||||||||
| </RadixTooltip> | ||||||||||
| ); | ||||||||||
| }); | ||||||||||
|
|
||||||||||
| function App() { | ||||||||||
| const data = useLoaderData<RootLoadersType>(); | ||||||||||
| const sessionTools = getSessionTools(); | ||||||||||
| const dapper = new DapperTs( | ||||||||||
| () => data.config, | ||||||||||
| () => | ||||||||||
| sessionTools.clearInvalidSession( | ||||||||||
| data?.publicEnvVariables.VITE_COOKIE_DOMAIN | ||||||||||
| ) | ||||||||||
| ); | ||||||||||
| const AdsColumn = memo(function AdsColumn({ | ||||||||||
| shouldShow, | ||||||||||
| }: { | ||||||||||
| shouldShow: boolean; | ||||||||||
| }) { | ||||||||||
| if (!shouldShow) return null; | ||||||||||
|
|
||||||||||
| return ( | ||||||||||
| <Outlet | ||||||||||
| context={{ | ||||||||||
| currentUser: data?.currentUser, | ||||||||||
| requestConfig: dapper.config, | ||||||||||
| domain: data?.publicEnvVariables.VITE_API_URL, | ||||||||||
| dapper: dapper, | ||||||||||
| }} | ||||||||||
| /> | ||||||||||
| <div className="container container--y island-item layout__ads"> | ||||||||||
| <div className="container container--y layout__ads-inner"> | ||||||||||
| {adContainerIds.map((cid, k_i) => ( | ||||||||||
| <AdContainer key={k_i} containerId={cid} /> | ||||||||||
|
Comment on lines
+378
to
+379
|
||||||||||
| {adContainerIds.map((cid, k_i) => ( | |
| <AdContainer key={k_i} containerId={cid} /> | |
| {adContainerIds.map((cid) => ( | |
| <AdContainer key={cid} containerId={cid} /> |
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -1,6 +1,16 @@ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| export function setParamsBlobValue< | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| SearchParamsType, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| K extends keyof SearchParamsType, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| >(setter: React.Dispatch<React.SetStateAction<SearchParamsType>>, key: K) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return (v: SearchParamsType[K]) => | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| setter((prevBlob) => ({ ...prevBlob, [key]: v })); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // Keep the old signature wrapper with `oldBlob` around for backward compatibility, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // although it should be refactored eventually. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| export function setParamsBlobValueLegacy< | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| SearchParamsType, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| K extends keyof SearchParamsType, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| >(setter: (v: SearchParamsType) => void, oldBlob: SearchParamsType, key: K) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return (v: SearchParamsType[K]) => setter({ ...oldBlob, [key]: v }); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
1
to
15
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| export function setParamsBlobValue< | |
| SearchParamsType, | |
| K extends keyof SearchParamsType, | |
| >(setter: React.Dispatch<React.SetStateAction<SearchParamsType>>, key: K) { | |
| return (v: SearchParamsType[K]) => | |
| setter((prevBlob) => ({ ...prevBlob, [key]: v })); | |
| } | |
| // Keep the old signature wrapper with `oldBlob` around for backward compatibility, | |
| // although it should be refactored eventually. | |
| export function setParamsBlobValueLegacy< | |
| SearchParamsType, | |
| K extends keyof SearchParamsType, | |
| >(setter: (v: SearchParamsType) => void, oldBlob: SearchParamsType, key: K) { | |
| return (v: SearchParamsType[K]) => setter({ ...oldBlob, [key]: v }); | |
| import type { Dispatch, SetStateAction } from 'react'; | |
| export function setParamsBlobValue< | |
| SearchParamsType, | |
| K extends keyof SearchParamsType, | |
| >(setter: (v: SearchParamsType) => void, oldBlob: SearchParamsType, key: K) { | |
| return (v: SearchParamsType[K]) => setter({ ...oldBlob, [key]: v }); | |
| } | |
| export function setParamsBlobValueFromStateSetter< | |
| SearchParamsType, | |
| K extends keyof SearchParamsType, | |
| >(setter: Dispatch<SetStateAction<SearchParamsType>>, key: K) { | |
| return (v: SearchParamsType[K]) => | |
| setter((prevBlob) => ({ ...prevBlob, [key]: v })); |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -8,7 +8,7 @@ import { | |
| } from "@fortawesome/free-solid-svg-icons"; | ||
| import { faLips } from "@fortawesome/pro-solid-svg-icons"; | ||
| import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; | ||
| import { useEffect, useState } from "react"; | ||
| import { memo, useEffect, useState } from "react"; | ||
| import ago from "s-ago"; | ||
|
|
||
| import { type CardPackageVariants } from "@thunderstore/cyberstorm-theme"; | ||
|
|
@@ -43,7 +43,7 @@ interface Props { | |
| rootClasses?: string; | ||
| } | ||
|
|
||
| export function CardPackage(props: Props) { | ||
| export const CardPackage = memo(function CardPackage(props: Props) { | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🧩 Analysis chain🏁 Script executed: #!/bin/bash
# Verify all usages of CardPackage to check for inline function props
rg -n -A 10 '<CardPackage' --type ts --type tsx -g '!*.test.*' -g '!*.spec.*'Repository: thunderstore-io/thunderstore-ui Length of output: 102 🏁 Script executed: #!/bin/bash
# Search for CardPackage component usage (corrected file type flags)
rg -n -A 10 '<CardPackage' --type ts --type jsxRepository: thunderstore-io/thunderstore-ui Length of output: 102 🏁 Script executed: #!/bin/bash
# Also check CardPackage.tsx file directly to confirm memo wrapper exists
wc -l packages/cyberstorm/src/newComponents/Card/CardPackage/CardPackage.tsxRepository: thunderstore-io/thunderstore-ui Length of output: 149 🏁 Script executed: #!/bin/bash
# Check the actual CardPackage.tsx around line 46
head -n 50 packages/cyberstorm/src/newComponents/Card/CardPackage/CardPackage.tsx | tail -n 15Repository: thunderstore-io/thunderstore-ui Length of output: 438 🏁 Script executed: #!/bin/bash
# Search for CardPackage usage without file type flags
rg '<CardPackage' -A 10 --max-count 20Repository: thunderstore-io/thunderstore-ui Length of output: 2425 🏁 Script executed: #!/bin/bash
# Check PackageSearch.tsx specifically around lines mentioned in review (406-416)
head -n 420 packages/cyberstorm/src/newComponents/PackageSearch/PackageSearch.tsx | tail -n 30Repository: thunderstore-io/thunderstore-ui Length of output: 203 🏁 Script executed: #!/bin/bash
# Get full context of the CardPackage usage in PackageSearch
rg -B 5 -A 20 'packageLikeAction=.*={() =>' apps/cyberstorm-remix/app/commonComponents/PackageSearch/PackageSearch.tsxRepository: thunderstore-io/thunderstore-ui Length of output: 206 🏁 Script executed: #!/bin/bash
# Check if useCallback is used elsewhere in PackageSearch
rg 'useCallback' apps/cyberstorm-remix/app/commonComponents/PackageSearch/PackageSearch.tsxRepository: thunderstore-io/thunderstore-ui Length of output: 121 🏁 Script executed: #!/bin/bash
# Search for all CardPackage usages to see if there are other call sites
rg -B 3 -A 15 '<CardPackage' --max-count 50Repository: thunderstore-io/thunderstore-ui Length of output: 4070 Inline callback defeats memoization effectiveness. The Since the file already uses 🤖 Prompt for AI Agents |
||
| const { | ||
| packageData, | ||
| isLiked, | ||
|
|
@@ -290,6 +290,6 @@ export function CardPackage(props: Props) { | |
| {csVariant === "fullWidth" ? cardFooter : null} | ||
| </div> | ||
| ); | ||
| } | ||
| }); | ||
|
|
||
| CardPackage.displayName = "CardPackage"; | ||
Check failure
Code scanning / ESLint
Disallow the `any` type Error