Use 'selectHasChannel' instead of the full 'selectMyChannelClaims' (#7427)

- selectMyChannelClaims depends on `byId`, which currently is always invalidated per update, so it is not memoized.

- Most of the use-cases just needs the ID or the length of the array anyways, so avoid generating a Claim array (in selectMyChannelClaims) unnecessarily -- the client need to reduce it back down to IDs again :/

- The simpler boolean also removes the need to memoize the selector, which saves a bit of memory.

Co-authored-by: infinite-persistence <inf.persistence@gmail.com>
This commit is contained in:
jessopb 2022-01-21 12:38:11 -05:00 committed by GitHub
parent 2f1fc941bb
commit ca0cd2ca75
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
15 changed files with 27 additions and 52 deletions

View file

@ -4,7 +4,6 @@ import {
makeSelectClaimForUri, makeSelectClaimForUri,
selectThumbnailForUri, selectThumbnailForUri,
selectHasChannels, selectHasChannels,
selectMyChannelClaims,
} from 'redux/selectors/claims'; } from 'redux/selectors/claims';
import { doCommentUpdate, doCommentList } from 'redux/actions/comments'; import { doCommentUpdate, doCommentList } from 'redux/actions/comments';
import { makeSelectChannelIsMuted } from 'redux/selectors/blocked'; import { makeSelectChannelIsMuted } from 'redux/selectors/blocked';
@ -31,8 +30,7 @@ const select = (state, props) => {
commentingEnabled: true, commentingEnabled: true,
othersReacts: selectOthersReactsForComment(state, reactionKey), othersReacts: selectOthersReactsForComment(state, reactionKey),
activeChannelClaim, activeChannelClaim,
hasChannels: selectHasChannels(state), // hasChannels: selectHasChannels(state),
myChannels: selectMyChannelClaims(state),
playingUri: selectPlayingUri(state), playingUri: selectPlayingUri(state),
stakedLevel: selectTotalStakedAmountForChannelUri(state, props.authorUri), stakedLevel: selectTotalStakedAmountForChannelUri(state, props.authorUri),
linkedCommentAncestors: selectLinkedCommentAncestors(state), linkedCommentAncestors: selectLinkedCommentAncestors(state),

View file

@ -47,7 +47,7 @@ type Props = {
commentModBlock: (string) => void, commentModBlock: (string) => void,
linkedCommentId?: string, linkedCommentId?: string,
linkedCommentAncestors: { [string]: Array<string> }, linkedCommentAncestors: { [string]: Array<string> },
myChannels: ?Array<ChannelClaim>, hasChannels: boolean,
commentingEnabled: boolean, commentingEnabled: boolean,
doToast: ({ message: string }) => void, doToast: ({ message: string }) => void,
isTopLevel?: boolean, isTopLevel?: boolean,
@ -92,7 +92,7 @@ function Comment(props: Props) {
linkedCommentId, linkedCommentId,
linkedCommentAncestors, linkedCommentAncestors,
commentingEnabled, commentingEnabled,
myChannels, hasChannels,
doToast, doToast,
isTopLevel, isTopLevel,
threadDepth, threadDepth,
@ -125,7 +125,6 @@ function Comment(props: Props) {
const [page, setPage] = useState(0); const [page, setPage] = useState(0);
const [advancedEditor] = usePersistedState('comment-editor-mode', false); const [advancedEditor] = usePersistedState('comment-editor-mode', false);
const [displayDeadComment, setDisplayDeadComment] = React.useState(false); const [displayDeadComment, setDisplayDeadComment] = React.useState(false);
const hasChannels = myChannels && myChannels.length > 0;
const likesCount = (othersReacts && othersReacts.like) || 0; const likesCount = (othersReacts && othersReacts.like) || 0;
const dislikesCount = (othersReacts && othersReacts.dislike) || 0; const dislikesCount = (othersReacts && othersReacts.dislike) || 0;
const totalLikesAndDislikes = likesCount + dislikesCount; const totalLikesAndDislikes = likesCount + dislikesCount;

View file

@ -27,7 +27,7 @@ type Props = {
fileInfo: FileListItem, fileInfo: FileListItem,
costInfo: ?{ cost: number }, costInfo: ?{ cost: number },
renderMode: string, renderMode: string,
myChannels: ?Array<ChannelClaim>, hasChannels: boolean,
hideRepost?: boolean, hideRepost?: boolean,
reactionsDisabled: boolean, reactionsDisabled: boolean,
download: (string) => void, download: (string) => void,
@ -44,7 +44,7 @@ function FileActions(props: Props) {
costInfo, costInfo,
renderMode, renderMode,
prepareEdit, prepareEdit,
myChannels, hasChannels,
hideRepost, hideRepost,
reactionsDisabled, reactionsDisabled,
} = props; } = props;
@ -55,7 +55,6 @@ function FileActions(props: Props) {
const isMobile = useIsMobile(); const isMobile = useIsMobile();
const webShareable = costInfo && costInfo.cost === 0 && RENDER_MODES.WEB_SHAREABLE_MODES.includes(renderMode); const webShareable = costInfo && costInfo.cost === 0 && RENDER_MODES.WEB_SHAREABLE_MODES.includes(renderMode);
const showDelete = claimIsMine || (fileInfo && (fileInfo.written_bytes > 0 || fileInfo.blobs_completed > 0)); const showDelete = claimIsMine || (fileInfo && (fileInfo.written_bytes > 0 || fileInfo.blobs_completed > 0));
const hasChannels = myChannels && myChannels.length > 0;
const claimId = claim && claim.claim_id; const claimId = claim && claim.claim_id;
const { signing_channel: signingChannel } = claim; const { signing_channel: signingChannel } = claim;
const channelName = signingChannel && signingChannel.name; const channelName = signingChannel && signingChannel.name;
@ -84,9 +83,7 @@ function FileActions(props: Props) {
{ENABLE_FILE_REACTIONS && !reactionsDisabled && <FileReactions uri={uri} />} {ENABLE_FILE_REACTIONS && !reactionsDisabled && <FileReactions uri={uri} />}
<ClaimSupportButton uri={uri} fileAction /> <ClaimSupportButton uri={uri} fileAction />
<ClaimCollectionAddButton uri={uri} fileAction /> <ClaimCollectionAddButton uri={uri} fileAction />
{!hideRepost && ( {!hideRepost && <ClaimRepostButton uri={uri} claim={claim} hasChannels={hasChannels} />}
<ClaimRepostButton uri={uri} claim={claim} hasChannels={hasChannels} />
)}
<Button <Button
className="button--file-action" className="button--file-action"
icon={ICONS.SHARE} icon={ICONS.SHARE}

View file

@ -15,7 +15,6 @@ import {
selectIsResolvingPublishUris, selectIsResolvingPublishUris,
selectMyClaimForUri, selectMyClaimForUri,
} from 'redux/selectors/publish'; } from 'redux/selectors/publish';
import { selectMyChannelClaims } from 'redux/selectors/claims';
import * as RENDER_MODES from 'constants/file_render_modes'; import * as RENDER_MODES from 'constants/file_render_modes';
import * as SETTINGS from 'constants/settings'; import * as SETTINGS from 'constants/settings';
import { doClaimInitialRewards } from 'redux/actions/rewards'; import { doClaimInitialRewards } from 'redux/actions/rewards';
@ -33,7 +32,7 @@ import {
import { makeSelectClientSetting } from 'redux/selectors/settings'; import { makeSelectClientSetting } from 'redux/selectors/settings';
import { makeSelectFileRenderModeForUri } from 'redux/selectors/content'; import { makeSelectFileRenderModeForUri } from 'redux/selectors/content';
import { selectUser } from 'redux/selectors/user'; import { selectUser } from 'redux/selectors/user';
import PublishPage from './view'; import PublishForm from './view';
const select = (state) => { const select = (state) => {
const myClaimForUri = selectMyClaimForUri(state); const myClaimForUri = selectMyClaimForUri(state);
@ -60,7 +59,6 @@ const select = (state) => {
modal: selectModal(state), modal: selectModal(state),
enablePublishPreview: makeSelectClientSetting(SETTINGS.ENABLE_PUBLISH_PREVIEW)(state), enablePublishPreview: makeSelectClientSetting(SETTINGS.ENABLE_PUBLISH_PREVIEW)(state),
activeChannelClaim: selectActiveChannelClaim(state), activeChannelClaim: selectActiveChannelClaim(state),
myChannels: selectMyChannelClaims(state),
incognito: selectIncognito(state), incognito: selectIncognito(state),
activeChannelStakedLevel: selectActiveChannelStakedLevel(state), activeChannelStakedLevel: selectActiveChannelStakedLevel(state),
isClaimingInitialRewards: selectIsClaimingInitialRewards(state), isClaimingInitialRewards: selectIsClaimingInitialRewards(state),
@ -79,4 +77,4 @@ const perform = (dispatch) => ({
claimInitialRewards: () => dispatch(doClaimInitialRewards()), claimInitialRewards: () => dispatch(doClaimInitialRewards()),
}); });
export default connect(select, perform)(PublishPage); export default connect(select, perform)(PublishForm);

View file

@ -3,7 +3,6 @@ import { doHideModal } from 'redux/actions/app';
import { import {
makeSelectClaimForUri, makeSelectClaimForUri,
selectTitleForUri, selectTitleForUri,
selectMyChannelClaims,
selectRepostError, selectRepostError,
selectRepostLoading, selectRepostLoading,
selectMyClaimsWithoutChannels, selectMyClaimsWithoutChannels,
@ -24,7 +23,6 @@ import { selectActiveChannelClaim, selectIncognito } from 'redux/selectors/app';
import RepostCreate from './view'; import RepostCreate from './view';
const select = (state, props) => ({ const select = (state, props) => ({
channels: selectMyChannelClaims(state),
claim: makeSelectClaimForUri(props.uri)(state), claim: makeSelectClaimForUri(props.uri)(state),
passedRepostClaim: makeSelectClaimForUri(props.name, false)(state), passedRepostClaim: makeSelectClaimForUri(props.name, false)(state),
passedRepostAmount: makeSelectEffectiveAmountForUri(props.name)(state), passedRepostAmount: makeSelectEffectiveAmountForUri(props.name)(state),

View file

@ -28,7 +28,6 @@ type Props = {
claim?: StreamClaim, claim?: StreamClaim,
enteredContentClaim?: StreamClaim, enteredContentClaim?: StreamClaim,
balance: number, balance: number,
channels: ?Array<ChannelClaim>,
doCheckPublishNameAvailability: (string) => Promise<*>, doCheckPublishNameAvailability: (string) => Promise<*>,
error: ?string, error: ?string,
reposting: boolean, reposting: boolean,

View file

@ -1,5 +1,5 @@
import { connect } from 'react-redux'; import { connect } from 'react-redux';
import { selectMyChannelClaims } from 'redux/selectors/claims'; import { selectHasChannels } from 'redux/selectors/claims';
import { selectWalletIsEncrypted } from 'redux/selectors/wallet'; import { selectWalletIsEncrypted } from 'redux/selectors/wallet';
import { doWalletStatus } from 'redux/actions/wallet'; import { doWalletStatus } from 'redux/actions/wallet';
import { selectUser, selectUserVerifiedEmail } from 'redux/selectors/user'; import { selectUser, selectUserVerifiedEmail } from 'redux/selectors/user';
@ -11,7 +11,7 @@ const select = (state) => ({
isAuthenticated: selectUserVerifiedEmail(state), isAuthenticated: selectUserVerifiedEmail(state),
walletEncrypted: selectWalletIsEncrypted(state), walletEncrypted: selectWalletIsEncrypted(state),
user: selectUser(state), user: selectUser(state),
myChannels: selectMyChannelClaims(state), hasChannels: selectHasChannels(state),
language: selectLanguage(state), language: selectLanguage(state),
}); });

View file

@ -10,17 +10,15 @@ import SyncToggle from 'component/syncToggle';
import { getPasswordFromCookie } from 'util/saved-passwords'; import { getPasswordFromCookie } from 'util/saved-passwords';
type Props = { type Props = {
// --- select ---
isAuthenticated: boolean, isAuthenticated: boolean,
walletEncrypted: boolean, walletEncrypted: boolean,
user: User, user: User,
myChannels: ?Array<ChannelClaim>, hasChannels: boolean,
// --- perform ---
doWalletStatus: () => void, doWalletStatus: () => void,
}; };
export default function SettingAccount(props: Props) { export default function SettingAccount(props: Props) {
const { isAuthenticated, walletEncrypted, myChannels, doWalletStatus } = props; const { isAuthenticated, walletEncrypted, hasChannels, doWalletStatus } = props;
const [storedPassword, setStoredPassword] = React.useState(false); const [storedPassword, setStoredPassword] = React.useState(false);
// Determine if password is stored. // Determine if password is stored.
@ -59,7 +57,7 @@ export default function SettingAccount(props: Props) {
<SyncToggle disabled={walletEncrypted && !storedPassword && storedPassword !== ''} /> <SyncToggle disabled={walletEncrypted && !storedPassword && storedPassword !== ''} />
{/* @endif */} {/* @endif */}
{myChannels && ( {hasChannels && (
<SettingsRow title={__('Comments')} subtitle={__('View your past comments.')}> <SettingsRow title={__('Comments')} subtitle={__('View your past comments.')}>
<Button <Button
button="inverse" button="inverse"

View file

@ -1,6 +1,6 @@
import { connect } from 'react-redux'; import { connect } from 'react-redux';
import { selectBalance } from 'redux/selectors/wallet'; import { selectBalance } from 'redux/selectors/wallet';
import { selectMyChannelClaims, makeSelectClaimForUri } from 'redux/selectors/claims'; import { makeSelectClaimForUri } from 'redux/selectors/claims';
import { doOpenModal } from 'redux/actions/app'; import { doOpenModal } from 'redux/actions/app';
import WalletSend from './view'; import WalletSend from './view';
import { withRouter } from 'react-router'; import { withRouter } from 'react-router';
@ -12,7 +12,6 @@ const perform = (dispatch) => ({
const select = (state, props) => ({ const select = (state, props) => ({
balance: selectBalance(state), balance: selectBalance(state),
channels: selectMyChannelClaims(state),
contentClaim: makeSelectClaimForUri(props.contentUri)(state), contentClaim: makeSelectClaimForUri(props.contentUri)(state),
snack: selectToast(state), snack: selectToast(state),
}); });

View file

@ -1,10 +1,5 @@
import { connect } from 'react-redux'; import { connect } from 'react-redux';
import { import { selectMyChannelUrls, selectFetchingMyChannels, makeSelectClaimIsPending } from 'redux/selectors/claims';
selectMyChannelClaims,
selectMyChannelUrls,
selectFetchingMyChannels,
makeSelectClaimIsPending,
} from 'redux/selectors/claims';
import { doFetchChannelListMine } from 'redux/actions/claims'; import { doFetchChannelListMine } from 'redux/actions/claims';
import { doSetActiveChannel } from 'redux/actions/app'; import { doSetActiveChannel } from 'redux/actions/app';
import { selectYoutubeChannels } from 'redux/selectors/user'; import { selectYoutubeChannels } from 'redux/selectors/user';
@ -22,7 +17,6 @@ const select = (state) => {
return { return {
channelUrls, channelUrls,
channels: selectMyChannelClaims(state),
fetchingChannels: selectFetchingMyChannels(state), fetchingChannels: selectFetchingMyChannels(state),
youtubeChannels: selectYoutubeChannels(state), youtubeChannels: selectYoutubeChannels(state),
pendingChannels, pendingChannels,

View file

@ -14,7 +14,6 @@ import HelpLink from 'component/common/help-link';
import { useHistory } from 'react-router'; import { useHistory } from 'react-router';
type Props = { type Props = {
channels: Array<ChannelClaim>,
channelUrls: Array<string>, channelUrls: Array<string>,
fetchChannelListMine: () => void, fetchChannelListMine: () => void,
fetchingChannels: boolean, fetchingChannels: boolean,

View file

@ -1,11 +1,11 @@
import { connect } from 'react-redux'; import { connect } from 'react-redux';
import { selectMyChannelClaims, selectFetchingMyChannels } from 'redux/selectors/claims'; import { selectHasChannels, selectFetchingMyChannels } from 'redux/selectors/claims';
import { selectActiveChannelClaim } from 'redux/selectors/app'; import { selectActiveChannelClaim } from 'redux/selectors/app';
import { doSetActiveChannel } from 'redux/actions/app'; import { doSetActiveChannel } from 'redux/actions/app';
import CreatorDashboardPage from './view'; import CreatorDashboardPage from './view';
const select = (state) => ({ const select = (state) => ({
channels: selectMyChannelClaims(state), hasChannels: selectHasChannels(state),
fetchingChannels: selectFetchingMyChannels(state), fetchingChannels: selectFetchingMyChannels(state),
activeChannelClaim: selectActiveChannelClaim(state), activeChannelClaim: selectActiveChannelClaim(state),
}); });

View file

@ -9,14 +9,13 @@ import ChannelSelector from 'component/channelSelector';
import Yrbl from 'component/yrbl'; import Yrbl from 'component/yrbl';
type Props = { type Props = {
channels: Array<ChannelClaim>, hasChannels: boolean,
fetchingChannels: boolean, fetchingChannels: boolean,
activeChannelClaim: ?ChannelClaim, activeChannelClaim: ?ChannelClaim,
}; };
export default function CreatorDashboardPage(props: Props) { export default function CreatorDashboardPage(props: Props) {
const { channels, fetchingChannels, activeChannelClaim } = props; const { hasChannels, fetchingChannels, activeChannelClaim } = props;
const hasChannels = channels && channels.length > 0;
return ( return (
<Page> <Page>

View file

@ -12,7 +12,7 @@ import {
selectModeratorTimeoutMap, selectModeratorTimeoutMap,
selectPersonalTimeoutMap, selectPersonalTimeoutMap,
} from 'redux/selectors/comments'; } from 'redux/selectors/comments';
import { selectMyChannelClaims } from 'redux/selectors/claims'; import { selectMyChannelClaimIds } from 'redux/selectors/claims';
import ListBlocked from './view'; import ListBlocked from './view';
const select = (state) => ({ const select = (state) => ({
@ -25,7 +25,7 @@ const select = (state) => ({
moderatorTimeoutMap: selectModeratorTimeoutMap(state), moderatorTimeoutMap: selectModeratorTimeoutMap(state),
moderatorBlockListDelegatorsMap: selectModeratorBlockListDelegatorsMap(state), moderatorBlockListDelegatorsMap: selectModeratorBlockListDelegatorsMap(state),
delegatorsById: selectModerationDelegatorsById(state), delegatorsById: selectModerationDelegatorsById(state),
myChannelClaims: selectMyChannelClaims(state), myChannelClaimIds: selectMyChannelClaimIds(state),
fetchingModerationBlockList: selectFetchingModerationBlockList(state), fetchingModerationBlockList: selectFetchingModerationBlockList(state),
}); });

View file

@ -34,7 +34,7 @@ type Props = {
fetchModBlockedList: () => void, fetchModBlockedList: () => void,
fetchModAmIList: () => void, fetchModAmIList: () => void,
delegatorsById: { [string]: { global: boolean, delegators: { name: string, claimId: string } } }, delegatorsById: { [string]: { global: boolean, delegators: { name: string, claimId: string } } },
myChannelClaims: ?Array<ChannelClaim>, myChannelClaimIds: ?Array<string>,
}; };
function ListBlocked(props: Props) { function ListBlocked(props: Props) {
@ -51,7 +51,7 @@ function ListBlocked(props: Props) {
fetchModBlockedList, fetchModBlockedList,
fetchModAmIList, fetchModAmIList,
delegatorsById, delegatorsById,
myChannelClaims, myChannelClaimIds,
} = props; } = props;
const [viewMode, setViewMode] = usePersistedState('blocked-muted:display', VIEW.BLOCKED); const [viewMode, setViewMode] = usePersistedState('blocked-muted:display', VIEW.BLOCKED);
@ -60,14 +60,11 @@ function ListBlocked(props: Props) {
const stringifiedDelegatorsMap = JSON.stringify(delegatorsMap); const stringifiedDelegatorsMap = JSON.stringify(delegatorsMap);
const stringifiedLocalDelegatorsMap = JSON.stringify(localDelegatorsMap); const stringifiedLocalDelegatorsMap = JSON.stringify(localDelegatorsMap);
const isAdmin = const isAdmin = myChannelClaimIds && myChannelClaimIds.some((id) => delegatorsById[id] && delegatorsById[id].global);
myChannelClaims && myChannelClaims.some((c) => delegatorsById[c.claim_id] && delegatorsById[c.claim_id].global);
const isModerator = const isModerator =
myChannelClaims && myChannelClaimIds &&
myChannelClaims.some( myChannelClaimIds.some((id) => delegatorsById[id] && Object.keys(delegatorsById[id].delegators).length > 0);
(c) => delegatorsById[c.claim_id] && Object.keys(delegatorsById[c.claim_id].delegators).length > 0
);
// ************************************************************************** // **************************************************************************
@ -221,7 +218,7 @@ function ListBlocked(props: Props) {
function getRefreshElem() { function getRefreshElem() {
return ( return (
myChannelClaims && ( myChannelClaimIds && (
<Button <Button
icon={ICONS.REFRESH} icon={ICONS.REFRESH}
button="alt" button="alt"