perf(react-doctor): fix compiler-blocking patterns, raise score 72→81

Replace sync setState-in-effect with keyed remount and render-derived patterns in app, error-display, topbar-edit-modal, catalog-filters; use useCurrentTime() instead of Date.now() in hot paths; fix conditional hooks, passive scroll listeners, lodash path imports.
This commit is contained in:
plebeius
2026-02-18 15:31:01 +08:00
parent afb50ad02d
commit e0ed510fc6
27 changed files with 213 additions and 200 deletions
+1 -1
View File
@@ -12,7 +12,7 @@ import useDirectoryModalStore from '../../stores/use-directory-modal-store';
import DisclaimerModal from '../../components/disclaimer-modal';
import DirectoryModal from '../../components/directory-modal';
import { getBoardPath } from '../../lib/utils/route-utils';
import { lowerCase } from 'lodash';
import lowerCase from 'lodash/lowerCase';
// https://github.com/bitsocialhq/lists/blob/master/5chan-directories.json
@@ -70,7 +70,7 @@ const PopularThreadsBox = ({ directories, subplebbits }: { directories: Director
const { t } = useTranslation();
const { showWorksafeContentOnly, showNsfwContentOnly } = usePopularThreadsOptionsStore();
const getFilteredSubplebbits = () => {
const filteredSubplebbits = useMemo(() => {
if (showWorksafeContentOnly) {
return subplebbits.filter((sub: Subplebbit) => {
const directoriesEntry = directories.find((ms) => ms?.address === sub?.address);
@@ -84,9 +84,7 @@ const PopularThreadsBox = ({ directories, subplebbits }: { directories: Director
});
}
return subplebbits;
};
const filteredSubplebbits = useMemo(getFilteredSubplebbits, [subplebbits, showWorksafeContentOnly, showNsfwContentOnly, directories]);
}, [subplebbits, showWorksafeContentOnly, showNsfwContentOnly, directories]);
const { popularPosts } = usePopularPosts(filteredSubplebbits);
const isLoading = popularPosts.length === 0;
+16 -11
View File
@@ -20,8 +20,10 @@ import useChallengesStore from '../../stores/use-challenges-store';
import { alertChallengeVerificationFailed } from '../../lib/utils/challenge-utils';
import Tooltip from '../../components/tooltip';
import useIsMobile from '../../hooks/use-is-mobile';
import { useCurrentTime } from '../../hooks/use-current-time';
import { Post } from '../post/post';
import { capitalize, lowerCase } from 'lodash';
import capitalize from 'lodash/capitalize';
import lowerCase from 'lodash/lowerCase';
const { addChallenge } = useChallengesStore.getState();
@@ -158,6 +160,7 @@ const ModQueueRow = ({ comment, isOdd = false }: ModQueueRowProps) => {
const { t } = useTranslation();
const { getAlertThresholdSeconds } = useModQueueStore();
const isMobile = useIsMobile();
const currentTime = useCurrentTime();
const { editedComment } = useEditedComment({ comment });
const displayComment = editedComment || comment;
@@ -171,7 +174,7 @@ const ModQueueRow = ({ comment, isOdd = false }: ModQueueRowProps) => {
const alreadyApproved = approved === true;
const alreadyRejected = removed === true;
const timeWaiting = Date.now() / 1000 - timestamp;
const timeWaiting = currentTime - timestamp;
const alertThresholdSeconds = getAlertThresholdSeconds();
const isOverThreshold = timeWaiting > alertThresholdSeconds;
@@ -287,6 +290,7 @@ interface ModQueueCardProps {
const ModQueueCard = ({ comment }: ModQueueCardProps) => {
const { t } = useTranslation();
const { getAlertThresholdSeconds } = useModQueueStore();
const currentTime = useCurrentTime();
const { editedComment } = useEditedComment({ comment });
const displayComment = editedComment || comment;
@@ -297,7 +301,7 @@ const ModQueueCard = ({ comment }: ModQueueCardProps) => {
const alreadyApproved = approved === true;
const alreadyRejected = removed === true;
const timeWaiting = Date.now() / 1000 - timestamp;
const timeWaiting = currentTime - timestamp;
const alertThresholdSeconds = getAlertThresholdSeconds();
const isOverThreshold = timeWaiting > alertThresholdSeconds;
const isAwaitingApproval = !alreadyApproved && !alreadyRejected;
@@ -441,21 +445,21 @@ const ModQueueBoardFilter = ({ communities }: ModQueueBoardFilterProps) => {
setSelectedBoardFilter(value);
};
if (!communities || communities.length === 0) {
return null;
}
// Default to first board if none selected
const firstBoardAddress = communities.find((sub) => sub.address)?.address;
// Compute derived values before any early return so hooks run unconditionally
const firstBoardAddress = communities?.find((sub) => sub.address)?.address;
const currentFilter = selectedBoardFilter || firstBoardAddress || '';
// Auto-select first board if none is selected
// Auto-select first board if none is selected (must run before early return)
useEffect(() => {
if (!selectedBoardFilter && firstBoardAddress) {
setSelectedBoardFilter(firstBoardAddress);
}
}, [selectedBoardFilter, firstBoardAddress, setSelectedBoardFilter]);
if (!communities || communities.length === 0) {
return null;
}
return (
<div className={styles.filterContainer}>
<label>{t('filter_by_board')}:</label>
@@ -488,10 +492,11 @@ interface ModQueueCountItemProps {
const ModQueueCountItem = ({ comment, alertThresholdSeconds, onStatusChange }: ModQueueCountItemProps) => {
const { editedComment } = useEditedComment({ comment });
const displayComment = editedComment || comment;
const currentTime = useCurrentTime();
const { cid, approved, removed, timestamp } = displayComment;
const isAwaiting = approved !== true && removed !== true;
const timeWaiting = Date.now() / 1000 - timestamp;
const timeWaiting = currentTime - timestamp;
const isUrgent = isAwaiting && timeWaiting > alertThresholdSeconds;
useEffect(() => {