pl-fe: limit rerenders
Signed-off-by: marcin mikołajczak <git@mkljczk.pl>
This commit is contained in:
parent
d3b5078030
commit
0a253894a6
5 changed files with 37 additions and 25 deletions
|
@ -32,7 +32,7 @@ const useAccount = (accountId?: string, opts: UseAccountOpts = {}) => {
|
||||||
{ enabled: !!accountId, transform: normalizeAccount },
|
{ enabled: !!accountId, transform: normalizeAccount },
|
||||||
);
|
);
|
||||||
|
|
||||||
const meta = useAppSelector((state) => accountId && state.accounts_meta[accountId] || {});
|
const meta = useAppSelector((state) => accountId && state.accounts_meta[accountId]);
|
||||||
|
|
||||||
const {
|
const {
|
||||||
relationship,
|
relationship,
|
||||||
|
|
|
@ -2,7 +2,7 @@ import React from 'react';
|
||||||
|
|
||||||
import { uploadCompose } from 'pl-fe/actions/compose';
|
import { uploadCompose } from 'pl-fe/actions/compose';
|
||||||
import { useAppDispatch } from 'pl-fe/hooks/useAppDispatch';
|
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';
|
import UploadButton from '../components/upload-button';
|
||||||
|
|
||||||
|
@ -14,10 +14,7 @@ interface IUploadButtonContainer {
|
||||||
|
|
||||||
const UploadButtonContainer: React.FC<IUploadButtonContainer> = ({ composeId }) => {
|
const UploadButtonContainer: React.FC<IUploadButtonContainer> = ({ composeId }) => {
|
||||||
const dispatch = useAppDispatch();
|
const dispatch = useAppDispatch();
|
||||||
const { disabled, resetFileKey } = useAppSelector((state) => ({
|
const { is_uploading: disabled, resetFileKey } = useCompose(composeId);
|
||||||
disabled: state.compose.get(composeId)?.is_uploading,
|
|
||||||
resetFileKey: state.compose.get(composeId)?.resetFileKey!,
|
|
||||||
}));
|
|
||||||
|
|
||||||
const onSelectFile = (files: FileList, intl: IntlShape) => {
|
const onSelectFile = (files: FileList, intl: IntlShape) => {
|
||||||
dispatch(uploadCompose(composeId, files, intl));
|
dispatch(uploadCompose(composeId, files, intl));
|
||||||
|
|
|
@ -3,14 +3,16 @@ import throttle from 'lodash/throttle';
|
||||||
import React, { useEffect, useMemo } from 'react';
|
import React, { useEffect, useMemo } from 'react';
|
||||||
import { defineMessages, useIntl } from 'react-intl';
|
import { defineMessages, useIntl } from 'react-intl';
|
||||||
import { Link } from 'react-router-dom';
|
import { Link } from 'react-router-dom';
|
||||||
|
import { createSelector } from 'reselect';
|
||||||
|
|
||||||
import { fetchOwnAccounts, logOut, switchAccount } from 'pl-fe/actions/auth';
|
import { fetchOwnAccounts, logOut, switchAccount } from 'pl-fe/actions/auth';
|
||||||
import Account from 'pl-fe/components/account';
|
import Account from 'pl-fe/components/account';
|
||||||
import DropdownMenu from 'pl-fe/components/dropdown-menu';
|
import DropdownMenu from 'pl-fe/components/dropdown-menu';
|
||||||
|
import { Entities } from 'pl-fe/entity-store/entities';
|
||||||
import { useAppDispatch } from 'pl-fe/hooks/useAppDispatch';
|
import { useAppDispatch } from 'pl-fe/hooks/useAppDispatch';
|
||||||
import { useAppSelector } from 'pl-fe/hooks/useAppSelector';
|
import { useAppSelector } from 'pl-fe/hooks/useAppSelector';
|
||||||
import { useFeatures } from 'pl-fe/hooks/useFeatures';
|
import { useFeatures } from 'pl-fe/hooks/useFeatures';
|
||||||
import { makeGetAccount } from 'pl-fe/selectors';
|
import { RootState } from 'pl-fe/store';
|
||||||
|
|
||||||
import ThemeToggle from './theme-toggle';
|
import ThemeToggle from './theme-toggle';
|
||||||
|
|
||||||
|
@ -35,15 +37,18 @@ type IMenuItem = {
|
||||||
action?: (event: React.MouseEvent) => void;
|
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 ProfileDropdown: React.FC<IProfileDropdown> = ({ account, children }) => {
|
||||||
const dispatch = useAppDispatch();
|
const dispatch = useAppDispatch();
|
||||||
const features = useFeatures();
|
const features = useFeatures();
|
||||||
const intl = useIntl();
|
const intl = useIntl();
|
||||||
|
|
||||||
const authUsers = useAppSelector((state) => state.auth.users);
|
const otherAccounts = useAppSelector(getOtherAccounts);
|
||||||
const otherAccounts = useAppSelector((state) => authUsers.map((authUser: any) => getAccount(state, authUser.id)!));
|
|
||||||
|
|
||||||
const handleLogOut = () => {
|
const handleLogOut = () => {
|
||||||
dispatch(logOut());
|
dispatch(logOut());
|
||||||
|
@ -66,7 +71,7 @@ const ProfileDropdown: React.FC<IProfileDropdown> = ({ account, children }) => {
|
||||||
|
|
||||||
menu.push({ text: renderAccount(account), to: `/@${account.acct}` });
|
menu.push({ text: renderAccount(account), to: `/@${account.acct}` });
|
||||||
|
|
||||||
otherAccounts.forEach((otherAccount: AccountEntity) => {
|
otherAccounts.forEach((otherAccount?: AccountEntity) => {
|
||||||
if (otherAccount && otherAccount.id !== account.id) {
|
if (otherAccount && otherAccount.id !== account.id) {
|
||||||
menu.push({
|
menu.push({
|
||||||
text: renderAccount(otherAccount),
|
text: renderAccount(otherAccount),
|
||||||
|
@ -99,11 +104,11 @@ const ProfileDropdown: React.FC<IProfileDropdown> = ({ account, children }) => {
|
||||||
))}
|
))}
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
}, [account, authUsers, features]);
|
}, [account, otherAccounts.length, features]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
fetchOwnAccountThrottled();
|
fetchOwnAccountThrottled();
|
||||||
}, [account.id, authUsers]);
|
}, [account.id, otherAccounts.length]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<DropdownMenu
|
<DropdownMenu
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
import { QueryClientProvider } from '@tanstack/react-query';
|
import { QueryClientProvider } from '@tanstack/react-query';
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { HelmetProvider } from 'react-helmet-async';
|
import { HelmetProvider } from 'react-helmet-async';
|
||||||
|
import { Toaster } from 'react-hot-toast';
|
||||||
import { Provider } from 'react-redux';
|
import { Provider } from 'react-redux';
|
||||||
|
|
||||||
import { StatProvider } from 'pl-fe/contexts/stat-context';
|
import { StatProvider } from 'pl-fe/contexts/stat-context';
|
||||||
|
@ -26,18 +27,26 @@ store.dispatch(checkOnboardingStatus() as any);
|
||||||
|
|
||||||
/** The root React node of the application. */
|
/** The root React node of the application. */
|
||||||
const PlFe: React.FC = () => (
|
const PlFe: React.FC = () => (
|
||||||
<Provider store={store}>
|
<>
|
||||||
<QueryClientProvider client={queryClient}>
|
<Provider store={store}>
|
||||||
<StatProvider>
|
<QueryClientProvider client={queryClient}>
|
||||||
<HelmetProvider>
|
<StatProvider>
|
||||||
<PlFeHead />
|
<HelmetProvider>
|
||||||
<PlFeLoad>
|
<PlFeHead />
|
||||||
<PlFeMount />
|
<PlFeLoad>
|
||||||
</PlFeLoad>
|
<PlFeMount />
|
||||||
</HelmetProvider>
|
</PlFeLoad>
|
||||||
</StatProvider>
|
</HelmetProvider>
|
||||||
</QueryClientProvider>
|
</StatProvider>
|
||||||
</Provider>
|
</QueryClientProvider>
|
||||||
|
</Provider>
|
||||||
|
<div id='toaster'>
|
||||||
|
<Toaster
|
||||||
|
position='top-right'
|
||||||
|
containerClassName='top-4'
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</>
|
||||||
);
|
);
|
||||||
|
|
||||||
export { PlFe as default };
|
export { PlFe as default };
|
||||||
|
|
|
@ -349,6 +349,7 @@ const makeGetStatusIds = () => createSelector([
|
||||||
export {
|
export {
|
||||||
type RemoteInstance,
|
type RemoteInstance,
|
||||||
selectAccount,
|
selectAccount,
|
||||||
|
selectAccounts,
|
||||||
selectOwnAccount,
|
selectOwnAccount,
|
||||||
makeGetAccount,
|
makeGetAccount,
|
||||||
getFilters,
|
getFilters,
|
||||||
|
|
Loading…
Reference in a new issue