diff --git a/packages/pl-fe/src/components/loading-screen.tsx b/packages/pl-fe/src/components/loading-screen.tsx index 7c53233e0..c826d0eb0 100644 --- a/packages/pl-fe/src/components/loading-screen.tsx +++ b/packages/pl-fe/src/components/loading-screen.tsx @@ -4,7 +4,7 @@ import LandingGradient from 'pl-fe/components/landing-gradient'; import Spinner from 'pl-fe/components/ui/spinner'; /** Fullscreen loading indicator. */ -const LoadingScreen: React.FC = () => ( +const LoadingScreen: React.FC = React.memo(() => (
@@ -14,6 +14,6 @@ const LoadingScreen: React.FC = () => (
-); +)); export { LoadingScreen as default }; diff --git a/packages/pl-fe/src/components/search-input.tsx b/packages/pl-fe/src/components/search-input.tsx index 36e571bf6..e15605be1 100644 --- a/packages/pl-fe/src/components/search-input.tsx +++ b/packages/pl-fe/src/components/search-input.tsx @@ -25,7 +25,7 @@ const redirectToAccount = (accountId: string, routerHistory: History) => } }; -const SearchInput = () => { +const SearchInput = React.memo(() => { const [value, setValue] = useState(''); const dispatch = useAppDispatch(); @@ -110,6 +110,6 @@ const SearchInput = () => { ); -}; +}); export { SearchInput as default }; diff --git a/packages/pl-fe/src/components/sidebar-menu.tsx b/packages/pl-fe/src/components/sidebar-menu.tsx index e94ec5ef7..9e8e2120b 100644 --- a/packages/pl-fe/src/components/sidebar-menu.tsx +++ b/packages/pl-fe/src/components/sidebar-menu.tsx @@ -1,6 +1,6 @@ /* eslint-disable jsx-a11y/interactive-supports-focus */ import clsx from 'clsx'; -import React, { useCallback, useEffect, useRef, useState } from 'react'; +import React, { useCallback, useEffect, useMemo, useRef, useState } from 'react'; import { defineMessages, useIntl, FormattedMessage } from 'react-intl'; import { Link, NavLink } from 'react-router-dom'; @@ -59,7 +59,7 @@ interface ISidebarLink { onClick: React.EventHandler; } -const SidebarLink: React.FC = ({ href, to, icon, text, onClick }) => { +const SidebarLink: React.FC = React.memo(({ href, to, icon, text, onClick }) => { const body = (
@@ -83,9 +83,10 @@ const SidebarLink: React.FC = ({ href, to, icon, text, onClick }) {body} ); -}; +}); -const SidebarMenu: React.FC = (): JSX.Element | null => { + +const SidebarMenu: React.FC = React.memo((): JSX.Element | null => { const intl = useIntl(); const dispatch = useAppDispatch(); @@ -493,6 +494,6 @@ const SidebarMenu: React.FC = (): JSX.Element | null => {
); -}; +}); export { SidebarMenu as default }; diff --git a/packages/pl-fe/src/components/status-action-bar.tsx b/packages/pl-fe/src/components/status-action-bar.tsx index b103eb7ab..6eeedba87 100644 --- a/packages/pl-fe/src/components/status-action-bar.tsx +++ b/packages/pl-fe/src/components/status-action-bar.tsx @@ -211,7 +211,6 @@ const ReplyButton: React.FC = ({ let replyTitle; let replyDisabled = false; - const replyCount = status.replies_count; if ((status.group as Group)?.membership_required && !groupRelationship?.member) { replyDisabled = true; @@ -237,7 +236,7 @@ const ReplyButton: React.FC = ({ title={replyTitle} icon={require('@tabler/icons/outline/message-circle.svg')} onClick={handleReplyClick} - count={replyCount} + count={status.replies_count} text={withLabels ? intl.formatMessage(messages.reply) : undefined} disabled={replyDisabled} theme={statusActionButtonTheme} diff --git a/packages/pl-fe/src/hooks/use-can-interact.ts b/packages/pl-fe/src/hooks/use-can-interact.ts index d3d42e2ca..915c0e47c 100644 --- a/packages/pl-fe/src/hooks/use-can-interact.ts +++ b/packages/pl-fe/src/hooks/use-can-interact.ts @@ -1,32 +1,36 @@ +import { useMemo } from 'react'; + import { useAppSelector } from './use-app-selector'; import type { InteractionPolicy, InteractionPolicyEntry } from 'pl-api'; import type { MinifiedStatus } from 'pl-fe/reducers/statuses'; -const useCanInteract = (status: Pick, type: keyof InteractionPolicy): { +const useCanInteract = (status: Pick, type: keyof InteractionPolicy): { canInteract: boolean; approvalRequired: boolean | null; allowed?: Array; } => { - const interactionPolicy = status.interaction_policy; - const me = useAppSelector(state => state.me); - if (me === status.account_id || interactionPolicy[type].always.includes('me')) return { - canInteract: true, - approvalRequired: false, - }; + return useMemo(() => { + const interactionPolicy = status.interaction_policy; - if (interactionPolicy[type].with_approval.includes('me')) return { - canInteract: true, - approvalRequired: true, - }; + if (me === status.account_id || interactionPolicy[type].always.includes('me')) return { + canInteract: true, + approvalRequired: false, + }; - return { - canInteract: false, - approvalRequired: null, - allowed: [...interactionPolicy[type].always, ...interactionPolicy[type].with_approval], - }; + if (interactionPolicy[type].with_approval.includes('me')) return { + canInteract: true, + approvalRequired: true, + }; + + return { + canInteract: false, + approvalRequired: null, + allowed: [...interactionPolicy[type].always, ...interactionPolicy[type].with_approval], + }; + }, [me, status.id, type]); }; export { useCanInteract };