pl-fe: limit rerenders

Signed-off-by: marcin mikołajczak <git@mkljczk.pl>
This commit is contained in:
marcin mikołajczak 2024-10-25 23:38:31 +02:00
parent d3b5078030
commit 0a253894a6
5 changed files with 37 additions and 25 deletions

View file

@ -32,7 +32,7 @@ const useAccount = (accountId?: string, opts: UseAccountOpts = {}) => {
{ enabled: !!accountId, transform: normalizeAccount },
);
const meta = useAppSelector((state) => accountId && state.accounts_meta[accountId] || {});
const meta = useAppSelector((state) => accountId && state.accounts_meta[accountId]);
const {
relationship,

View file

@ -2,7 +2,7 @@ import React from 'react';
import { uploadCompose } from 'pl-fe/actions/compose';
import { useAppDispatch } from 'pl-fe/hooks/useAppDispatch';
import { useAppSelector } from 'pl-fe/hooks/useAppSelector';
import { useCompose } from 'pl-fe/hooks/useCompose';
import UploadButton from '../components/upload-button';
@ -14,10 +14,7 @@ interface IUploadButtonContainer {
const UploadButtonContainer: React.FC<IUploadButtonContainer> = ({ composeId }) => {
const dispatch = useAppDispatch();
const { disabled, resetFileKey } = useAppSelector((state) => ({
disabled: state.compose.get(composeId)?.is_uploading,
resetFileKey: state.compose.get(composeId)?.resetFileKey!,
}));
const { is_uploading: disabled, resetFileKey } = useCompose(composeId);
const onSelectFile = (files: FileList, intl: IntlShape) => {
dispatch(uploadCompose(composeId, files, intl));

View file

@ -3,14 +3,16 @@ import throttle from 'lodash/throttle';
import React, { useEffect, useMemo } from 'react';
import { defineMessages, useIntl } from 'react-intl';
import { Link } from 'react-router-dom';
import { createSelector } from 'reselect';
import { fetchOwnAccounts, logOut, switchAccount } from 'pl-fe/actions/auth';
import Account from 'pl-fe/components/account';
import DropdownMenu from 'pl-fe/components/dropdown-menu';
import { Entities } from 'pl-fe/entity-store/entities';
import { useAppDispatch } from 'pl-fe/hooks/useAppDispatch';
import { useAppSelector } from 'pl-fe/hooks/useAppSelector';
import { useFeatures } from 'pl-fe/hooks/useFeatures';
import { makeGetAccount } from 'pl-fe/selectors';
import { RootState } from 'pl-fe/store';
import ThemeToggle from './theme-toggle';
@ -35,15 +37,18 @@ type IMenuItem = {
action?: (event: React.MouseEvent) => void;
}
const getAccount = makeGetAccount();
const getOtherAccounts = createSelector([
(state: RootState) => state.auth.users,
(state: RootState) => state.entities[Entities.ACCOUNTS]?.store,
], (signedAccounts, accountEntities) => signedAccounts.toArray().map(([_, { id }]) => accountEntities?.[id] as AccountEntity).filter(account => account));
const ProfileDropdown: React.FC<IProfileDropdown> = ({ account, children }) => {
const dispatch = useAppDispatch();
const features = useFeatures();
const intl = useIntl();
const authUsers = useAppSelector((state) => state.auth.users);
const otherAccounts = useAppSelector((state) => authUsers.map((authUser: any) => getAccount(state, authUser.id)!));
const otherAccounts = useAppSelector(getOtherAccounts);
const handleLogOut = () => {
dispatch(logOut());
@ -66,7 +71,7 @@ const ProfileDropdown: React.FC<IProfileDropdown> = ({ account, children }) => {
menu.push({ text: renderAccount(account), to: `/@${account.acct}` });
otherAccounts.forEach((otherAccount: AccountEntity) => {
otherAccounts.forEach((otherAccount?: AccountEntity) => {
if (otherAccount && otherAccount.id !== account.id) {
menu.push({
text: renderAccount(otherAccount),
@ -99,11 +104,11 @@ const ProfileDropdown: React.FC<IProfileDropdown> = ({ account, children }) => {
))}
</>
);
}, [account, authUsers, features]);
}, [account, otherAccounts.length, features]);
useEffect(() => {
fetchOwnAccountThrottled();
}, [account.id, authUsers]);
}, [account.id, otherAccounts.length]);
return (
<DropdownMenu

View file

@ -1,6 +1,7 @@
import { QueryClientProvider } from '@tanstack/react-query';
import React from 'react';
import { HelmetProvider } from 'react-helmet-async';
import { Toaster } from 'react-hot-toast';
import { Provider } from 'react-redux';
import { StatProvider } from 'pl-fe/contexts/stat-context';
@ -26,18 +27,26 @@ store.dispatch(checkOnboardingStatus() as any);
/** The root React node of the application. */
const PlFe: React.FC = () => (
<Provider store={store}>
<QueryClientProvider client={queryClient}>
<StatProvider>
<HelmetProvider>
<PlFeHead />
<PlFeLoad>
<PlFeMount />
</PlFeLoad>
</HelmetProvider>
</StatProvider>
</QueryClientProvider>
</Provider>
<>
<Provider store={store}>
<QueryClientProvider client={queryClient}>
<StatProvider>
<HelmetProvider>
<PlFeHead />
<PlFeLoad>
<PlFeMount />
</PlFeLoad>
</HelmetProvider>
</StatProvider>
</QueryClientProvider>
</Provider>
<div id='toaster'>
<Toaster
position='top-right'
containerClassName='top-4'
/>
</div>
</>
);
export { PlFe as default };

View file

@ -349,6 +349,7 @@ const makeGetStatusIds = () => createSelector([
export {
type RemoteInstance,
selectAccount,
selectAccounts,
selectOwnAccount,
makeGetAccount,
getFilters,