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 };