Don't update 'pendingById' if no changes.

'pendingById' isn't frequently updated, but using it as a proof-of-concept to fix how reducers should be written to avoid unnecessary updates.

ImmutableJS apparently does all of this for us, but there are cons to using it as well, so using own wrappers for now.
This commit is contained in:
infinite-persistence 2021-11-08 13:26:05 +08:00
parent 121b0f0cd6
commit de2bec4425
No known key found for this signature in database
GPG key ID: B9C3252EDC3D0AA0

View file

@ -111,6 +111,29 @@ const defaultState = {
checkingReflecting: false, checkingReflecting: false,
}; };
// ****************************************************************************
// Helpers
// ****************************************************************************
function isObjEmpty(object: any) {
return Object.keys(object).length === 0;
}
function resolveDelta(original: any, delta: any) {
if (isObjEmpty(delta)) {
// Don't invalidate references when there are no changes, so return original.
return original;
} else {
// When there are changes: create a new object, spread existing references,
// and overwrite specific items with new data.
return { ...original, ...delta };
}
}
// ****************************************************************************
// handleClaimAction
// ****************************************************************************
function handleClaimAction(state: State, action: any): State { function handleClaimAction(state: State, action: any): State {
const { resolveInfo }: ClaimActionResolveInfo = action.data; const { resolveInfo }: ClaimActionResolveInfo = action.data;
@ -201,6 +224,10 @@ function handleClaimAction(state: State, action: any): State {
}); });
} }
// ****************************************************************************
// Reducers
// ****************************************************************************
reducers[ACTIONS.RESOLVE_URIS_STARTED] = (state: State, action: any): State => { reducers[ACTIONS.RESOLVE_URIS_STARTED] = (state: State, action: any): State => {
const { uris }: { uris: Array<string> } = action.data; const { uris }: { uris: Array<string> } = action.data;
@ -237,7 +264,8 @@ reducers[ACTIONS.FETCH_CLAIM_LIST_MINE_COMPLETED] = (state: State, action: any):
const byId = Object.assign({}, state.byId); const byId = Object.assign({}, state.byId);
const byUri = Object.assign({}, state.claimsByUri); const byUri = Object.assign({}, state.claimsByUri);
const pendingById = Object.assign({}, state.pendingById); const pendingByIdDelta = {};
let myClaimIds = new Set(state.myClaims); let myClaimIds = new Set(state.myClaims);
let urlsForCurrentPage = []; let urlsForCurrentPage = [];
@ -245,8 +273,10 @@ reducers[ACTIONS.FETCH_CLAIM_LIST_MINE_COMPLETED] = (state: State, action: any):
const { permanent_url: permanentUri, claim_id: claimId, canonical_url: canonicalUri } = claim; const { permanent_url: permanentUri, claim_id: claimId, canonical_url: canonicalUri } = claim;
if (claim.type && claim.type.match(/claim|update/)) { if (claim.type && claim.type.match(/claim|update/)) {
urlsForCurrentPage.push(permanentUri); urlsForCurrentPage.push(permanentUri);
if (claim.confirmations < 1) { if (claim.confirmations < 1) {
pendingById[claimId] = claim; pendingByIdDelta[claimId] = claim;
if (byId[claimId]) { if (byId[claimId]) {
byId[claimId] = mergeClaim(claim, byId[claimId]); byId[claimId] = mergeClaim(claim, byId[claimId]);
} else { } else {
@ -255,6 +285,7 @@ reducers[ACTIONS.FETCH_CLAIM_LIST_MINE_COMPLETED] = (state: State, action: any):
} else { } else {
byId[claimId] = claim; byId[claimId] = claim;
} }
byUri[permanentUri] = claimId; byUri[permanentUri] = claimId;
byUri[canonicalUri] = claimId; byUri[canonicalUri] = claimId;
myClaimIds.add(claimId); myClaimIds.add(claimId);
@ -265,7 +296,7 @@ reducers[ACTIONS.FETCH_CLAIM_LIST_MINE_COMPLETED] = (state: State, action: any):
isFetchingClaimListMine: false, isFetchingClaimListMine: false,
myClaims: Array.from(myClaimIds), myClaims: Array.from(myClaimIds),
byId, byId,
pendingById, pendingById: resolveDelta(state.pendingById, pendingByIdDelta),
claimsByUri: byUri, claimsByUri: byUri,
myClaimsPageResults: urlsForCurrentPage, myClaimsPageResults: urlsForCurrentPage,
myClaimsPageNumber: page, myClaimsPageNumber: page,
@ -279,7 +310,7 @@ reducers[ACTIONS.FETCH_CHANNEL_LIST_STARTED] = (state: State): State =>
reducers[ACTIONS.FETCH_CHANNEL_LIST_COMPLETED] = (state: State, action: any): State => { reducers[ACTIONS.FETCH_CHANNEL_LIST_COMPLETED] = (state: State, action: any): State => {
const { claims }: { claims: Array<ChannelClaim> } = action.data; const { claims }: { claims: Array<ChannelClaim> } = action.data;
let myClaimIds = new Set(state.myClaims); let myClaimIds = new Set(state.myClaims);
const pendingById = Object.assign({}, state.pendingById); const pendingByIdDelta = {};
let myChannelClaims; let myChannelClaims;
const byId = Object.assign({}, state.byId); const byId = Object.assign({}, state.byId);
const byUri = Object.assign({}, state.claimsByUri); const byUri = Object.assign({}, state.claimsByUri);
@ -302,8 +333,10 @@ reducers[ACTIONS.FETCH_CHANNEL_LIST_COMPLETED] = (state: State, action: any): St
// $FlowFixMe // $FlowFixMe
myChannelClaims.add(claimId); myChannelClaims.add(claimId);
if (confirmations < 1) { if (confirmations < 1) {
pendingById[claimId] = claim; pendingByIdDelta[claimId] = claim;
if (byId[claimId]) { if (byId[claimId]) {
byId[claimId] = mergeClaim(claim, byId[claimId]); byId[claimId] = mergeClaim(claim, byId[claimId]);
} else { } else {
@ -312,13 +345,14 @@ reducers[ACTIONS.FETCH_CHANNEL_LIST_COMPLETED] = (state: State, action: any): St
} else { } else {
byId[claimId] = claim; byId[claimId] = claim;
} }
myClaimIds.add(claimId); myClaimIds.add(claimId);
}); });
} }
return Object.assign({}, state, { return Object.assign({}, state, {
byId, byId,
pendingById, pendingById: resolveDelta(state.pendingById, pendingByIdDelta),
claimsByUri: byUri, claimsByUri: byUri,
channelClaimCounts, channelClaimCounts,
fetchingMyChannels: false, fetchingMyChannels: false,
@ -342,7 +376,7 @@ reducers[ACTIONS.FETCH_COLLECTION_LIST_COMPLETED] = (state: State, action: any):
const { claims }: { claims: Array<CollectionClaim> } = action.data; const { claims }: { claims: Array<CollectionClaim> } = action.data;
const myClaims = state.myClaims || []; const myClaims = state.myClaims || [];
let myClaimIds = new Set(myClaims); let myClaimIds = new Set(myClaims);
const pendingById = Object.assign({}, state.pendingById); const pendingByIdDelta = {};
let myCollectionClaimsSet = new Set([]); let myCollectionClaimsSet = new Set([]);
const byId = Object.assign({}, state.byId); const byId = Object.assign({}, state.byId);
const byUri = Object.assign({}, state.claimsByUri); const byUri = Object.assign({}, state.claimsByUri);
@ -357,9 +391,11 @@ reducers[ACTIONS.FETCH_COLLECTION_LIST_COMPLETED] = (state: State, action: any):
// $FlowFixMe // $FlowFixMe
myCollectionClaimsSet.add(claimId); myCollectionClaimsSet.add(claimId);
// we don't want to overwrite a pending result with a resolve // we don't want to overwrite a pending result with a resolve
if (confirmations < 1) { if (confirmations < 1) {
pendingById[claimId] = claim; pendingByIdDelta[claimId] = claim;
if (byId[claimId]) { if (byId[claimId]) {
byId[claimId] = mergeClaim(claim, byId[claimId]); byId[claimId] = mergeClaim(claim, byId[claimId]);
} else { } else {
@ -368,6 +404,7 @@ reducers[ACTIONS.FETCH_COLLECTION_LIST_COMPLETED] = (state: State, action: any):
} else { } else {
byId[claimId] = claim; byId[claimId] = claim;
} }
myClaimIds.add(claimId); myClaimIds.add(claimId);
}); });
} }
@ -375,7 +412,7 @@ reducers[ACTIONS.FETCH_COLLECTION_LIST_COMPLETED] = (state: State, action: any):
return { return {
...state, ...state,
byId, byId,
pendingById, pendingById: resolveDelta(state.pendingById, pendingByIdDelta),
claimsByUri: byUri, claimsByUri: byUri,
fetchingMyCollections: false, fetchingMyCollections: false,
myCollectionClaims: Array.from(myCollectionClaimsSet), myCollectionClaims: Array.from(myCollectionClaimsSet),