Fix missed render when blocklist is fetched

## Issue
7176

## Changes
Pitfalls of pausing render via React.memo:
  - We'll miss the `doClaimSearch()` since that is sparked by an `useEffect`.

Seems like we can't avoid having a redundant copy of the previously-displayed URIs.
This commit is contained in:
infinite-persistence 2021-09-29 09:53:11 +08:00
parent ddc29ac853
commit b796ab3207
No known key found for this signature in database
GPG key ID: B9C3252EDC3D0AA0
2 changed files with 16 additions and 20 deletions

View file

@ -73,7 +73,7 @@ function resolveSearchOptions(props) {
const mutedAndBlockedChannelIds = Array.from( const mutedAndBlockedChannelIds = Array.from(
new Set((mutedUris || []).concat(blockedUris || []).map((uri) => splitBySeparator(uri)[1])) new Set((mutedUris || []).concat(blockedUris || []).map((uri) => splitBySeparator(uri)[1]))
); ).sort();
const urlParams = new URLSearchParams(location.search); const urlParams = new URLSearchParams(location.search);
const feeAmountInUrl = urlParams.get('fee_amount'); const feeAmountInUrl = urlParams.get('fee_amount');

View file

@ -4,6 +4,7 @@ import React from 'react';
import { createNormalizedClaimSearchKey } from 'lbry-redux'; import { createNormalizedClaimSearchKey } from 'lbry-redux';
import ClaimPreviewTile from 'component/claimPreviewTile'; import ClaimPreviewTile from 'component/claimPreviewTile';
import useFetchViewCount from 'effects/use-fetch-view-count'; import useFetchViewCount from 'effects/use-fetch-view-count';
import usePrevious from 'effects/use-previous';
type SearchOptions = { type SearchOptions = {
page_size: number, page_size: number,
@ -99,6 +100,7 @@ function ClaimTilesDiscover(props: Props) {
const searchKey = createNormalizedClaimSearchKey(options); const searchKey = createNormalizedClaimSearchKey(options);
const fetchingClaimSearch = fetchingClaimSearchByQuery[searchKey]; const fetchingClaimSearch = fetchingClaimSearchByQuery[searchKey];
const claimSearchUris = claimSearchByQuery[searchKey] || []; const claimSearchUris = claimSearchByQuery[searchKey] || [];
const isUnfetchedClaimSearch = claimSearchByQuery[searchKey] === undefined;
// Don't use the query from createNormalizedClaimSearchKey for the effect since that doesn't include page & release_time // Don't use the query from createNormalizedClaimSearchKey for the effect since that doesn't include page & release_time
const optionsStringForEffect = JSON.stringify(options); const optionsStringForEffect = JSON.stringify(options);
@ -123,6 +125,8 @@ function ClaimTilesDiscover(props: Props) {
uris.push(...Array(pageSize - uris.length).fill('')); uris.push(...Array(pageSize - uris.length).fill(''));
} }
const prevUris = usePrevious(uris);
useFetchViewCount(fetchViewCount, uris, claimsByUri, doFetchViewCount); useFetchViewCount(fetchViewCount, uris, claimsByUri, doFetchViewCount);
// Run `doClaimSearch` // Run `doClaimSearch`
@ -133,10 +137,13 @@ function ClaimTilesDiscover(props: Props) {
} }
}, [doClaimSearch, shouldPerformSearch, optionsStringForEffect]); }, [doClaimSearch, shouldPerformSearch, optionsStringForEffect]);
// Show previous results while we fetch to avoid blinkies and poor CLS.
const finalUris = isUnfetchedClaimSearch && prevUris ? prevUris : uris;
return ( return (
<ul className="claim-grid"> <ul className="claim-grid">
{uris && uris.length {finalUris && finalUris.length
? uris.map((uri, i) => { ? finalUris.map((uri, i) => {
if (uri) { if (uri) {
return ( return (
<ClaimPreviewTile <ClaimPreviewTile
@ -172,29 +179,18 @@ function areEqual(prev: Props, next: Props) {
const prevSearchKey = createNormalizedClaimSearchKey(prevOptions); const prevSearchKey = createNormalizedClaimSearchKey(prevOptions);
const nextSearchKey = createNormalizedClaimSearchKey(nextOptions); const nextSearchKey = createNormalizedClaimSearchKey(nextOptions);
// "Pause" render when fetching to solve the layout-shift problem in #5979 if (prevSearchKey !== nextSearchKey) {
// (previous solution used a stashed copy of the rendered uris while fetching debug_trace('search key');
// to make it stay still). return false;
// This version works as long as we are not doing anything during a fetch,
// such as showing a spinner.
const nextCsFetch = next.fetchingClaimSearchByQuery[nextSearchKey];
if (nextCsFetch) {
return true;
} }
// --- Deep-compare --- // --- Deep-compare ---
if (prev.claimSearchByQuery[prevSearchKey] !== next.claimSearchByQuery[nextSearchKey]) { if (!urisEqual(prev.claimSearchByQuery[prevSearchKey], next.claimSearchByQuery[nextSearchKey])) {
debug_trace('claimSearchByQuery'); debug_trace('claimSearchByQuery');
return false; return false;
} }
if (prev.fetchingClaimSearchByQuery[prevSearchKey] !== next.fetchingClaimSearchByQuery[nextSearchKey]) {
debug_trace('fetchingClaimSearchByQuery');
return false;
}
const ARRAY_KEYS = ['prefixUris', 'channelIds', 'mutedUris', 'blockedUris']; const ARRAY_KEYS = ['prefixUris', 'channelIds', 'mutedUris', 'blockedUris'];
for (let i = 0; i < ARRAY_KEYS.length; ++i) { for (let i = 0; i < ARRAY_KEYS.length; ++i) {
const key = ARRAY_KEYS[i]; const key = ARRAY_KEYS[i];
if (!urisEqual(prev[key], next[key])) { if (!urisEqual(prev[key], next[key])) {
@ -209,12 +205,12 @@ function areEqual(prev: Props, next: Props) {
const KEYS_TO_IGNORE = [ const KEYS_TO_IGNORE = [
...ARRAY_KEYS, ...ARRAY_KEYS,
'claimSearchByQuery', 'claimSearchByQuery',
'fetchingClaimSearchByQuery', 'fetchingClaimSearchByQuery', // We are showing previous results while fetching.
'options', // Covered by search-key comparison.
'location', 'location',
'history', 'history',
'match', 'match',
'claimsByUri', 'claimsByUri',
'options',
'doClaimSearch', 'doClaimSearch',
'doToggleTagFollowDesktop', 'doToggleTagFollowDesktop',
]; ];