f5034f74ca
Expanded homepage pins to support 2 types of input (if both are passed in, pinnedUrls take precedence): (1) pinnedUrls --> uses doResolveUris (resolve) (2) pinnedClaimIds --> uses doResolveClaimIds (claim_search) Instead of injecting the pinned URLs directly, we inject from `resolvedPinUris`, which will be blank until the uris are resolved, thus preventing it from being resolved individually from the tiles. There's additional complexity with the `claim_search` method, as the rest of the code deals with uris instead of IDs. Fortunately, it's all contained with `useResolvePins`, so removal would be easier when the batch `resolve` issue is fixed.
51 lines
2.1 KiB
JavaScript
51 lines
2.1 KiB
JavaScript
// @flow
|
|
import React from 'react';
|
|
import useFetched from 'effects/use-fetched';
|
|
|
|
type Props = {
|
|
pins?: { urls?: Array<string>, claimIds?: Array<string>, onlyPinForOrder?: string },
|
|
claimsById: { [string]: Claim },
|
|
doResolveClaimIds: (Array<string>) => Promise<any>,
|
|
doResolveUris: (Array<string>, boolean) => Promise<any>,
|
|
};
|
|
|
|
export default function useResolvePins(props: Props) {
|
|
const { pins, claimsById, doResolveClaimIds, doResolveUris } = props;
|
|
|
|
const [resolvedPinUris, setResolvedPinUris] = React.useState(pins ? undefined : null);
|
|
const [resolvingPinUris, setResolvingPinUris] = React.useState(false);
|
|
const hasResolvedPinUris = useFetched(resolvingPinUris);
|
|
|
|
React.useEffect(() => {
|
|
if (resolvedPinUris === undefined && pins && !resolvingPinUris) {
|
|
if (pins.urls) {
|
|
doResolveUris(pins.urls, true).finally(() => setResolvedPinUris(pins.urls));
|
|
} else if (pins.claimIds) {
|
|
// setResolvingPinUris is only needed for claim_search.
|
|
// doResolveUris uses selectResolvingUris internally to prevent double call.
|
|
setResolvingPinUris(true);
|
|
|
|
// We can't use .then() here to grab the `claim_search` uris directly,
|
|
// because we skip those that are already resolved. Instead, we mark a
|
|
// flag here, then populate the array in the other effect below in the
|
|
// next render cycle (redux would be updated by then). Pretty dumb.
|
|
// $FlowFixMe: already checked for null `pins`, but flow can't see it when there's code above it? Wow.
|
|
doResolveClaimIds(pins.claimIds).finally(() => setResolvingPinUris(false));
|
|
} else {
|
|
setResolvedPinUris(null);
|
|
}
|
|
}
|
|
}, [resolvedPinUris, pins, doResolveUris, doResolveClaimIds, resolvingPinUris]);
|
|
|
|
React.useEffect(() => {
|
|
if (hasResolvedPinUris) {
|
|
if (pins && pins.claimIds) {
|
|
setResolvedPinUris(pins.claimIds.map<string>((id) => claimsById[id]?.canonical_url));
|
|
}
|
|
}
|
|
// Only do this over a false->true->false transition for hasResolvedPinUris.
|
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
}, [hasResolvedPinUris]);
|
|
|
|
return resolvedPinUris;
|
|
}
|