52 lines
2.1 KiB
JavaScript
52 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;
|
||
|
}
|