From b029a01bd96e93e574ffc2fdeb2fc94392ee2da4 Mon Sep 17 00:00:00 2001 From: Wyatt Johnson Date: Thu, 6 Aug 2020 08:56:57 -0600 Subject: [PATCH] setTimeout Fixes (#3082) * fix: fixed types and some unmanaged timeouts * fix: refetch type Co-authored-by: Chi Vinh Le Co-authored-by: kodiakhq[bot] <49736102+kodiakhq[bot]@users.noreply.github.com> --- src/core/client/auth/hooks/useResizePopup.ts | 10 +-- .../framework/components/CopyButton.tsx | 64 ++++++++----------- src/core/client/framework/lib/relay/fetch.tsx | 46 +++++++++---- .../EditCommentFormContainer.tsx | 8 ++- 4 files changed, 70 insertions(+), 58 deletions(-) diff --git a/src/core/client/auth/hooks/useResizePopup.ts b/src/core/client/auth/hooks/useResizePopup.ts index 43b12fe4c2..7931a7d0c9 100644 --- a/src/core/client/auth/hooks/useResizePopup.ts +++ b/src/core/client/auth/hooks/useResizePopup.ts @@ -6,7 +6,7 @@ import resizePopup from "../dom/resizePopup"; export default function useResizePopup() { const polling = useRef(true); - const pollTimeout = useRef(null); + const pollTimeout = useRef(null); const pollPopupHeight = useCallback((interval = 200) => { if (!polling.current) { @@ -16,7 +16,7 @@ export default function useResizePopup() { // Save the reference to the browser timeout we create. pollTimeout.current = // Create the timeout to fire after the interval. - setTimeout(() => { + window.setTimeout(() => { // Using requestAnimationFrame, resize the popup, and reschedule the // resize timeout again in another interval. window.requestAnimationFrame(() => { @@ -31,13 +31,13 @@ export default function useResizePopup() { pollPopupHeight(); return () => { - if (pollTimeout) { - clearTimeout(pollTimeout.current); + if (pollTimeout.current) { + window.clearTimeout(pollTimeout.current); pollTimeout.current = null; polling.current = false; } }; - }, []); + }, [pollPopupHeight]); const ref = useResizeObserver(() => { resizePopup(); diff --git a/src/core/client/framework/components/CopyButton.tsx b/src/core/client/framework/components/CopyButton.tsx index 31dd7d5b83..0be5aa0eb0 100644 --- a/src/core/client/framework/components/CopyButton.tsx +++ b/src/core/client/framework/components/CopyButton.tsx @@ -3,7 +3,6 @@ import React, { FunctionComponent, useCallback, useEffect, - useMemo, useState, } from "react"; import CopyToClipboard from "react-copy-to-clipboard"; @@ -25,53 +24,44 @@ const CopyButton: FunctionComponent = ({ innerCopied, ...rest }) => { - let timeout: any = null; const [copied, setCopied] = useState(false); - - // clear time out when we de-scope - useEffect(() => { - return function cleanup() { - clearTimeout(timeout); - }; - }, [timeout]); - - const timeoutCallback = useCallback(() => { - setCopied(false); - }, [setCopied]); - const handleCopy = useCallback(() => { setCopied(true); - clearTimeout(timeout); - timeout = setTimeout(timeoutCallback, 500); - }, [timeout, setCopied]); + }, [setCopied]); - const copyBody = useMemo(() => { - if (inner) { - return inner; + // Handle the animation event associated with toggling the copied state. + useEffect(() => { + if (!copied) { + return; } - return ( - - Copy - - ); - }, [inner]); - const copiedBody = useMemo(() => { - if (innerCopied) { - return innerCopied; - } + const timeout = window.setTimeout(() => { + setCopied(false); + }, 500); - return ( - - Copied! - - ); - }, [innerCopied]); + return () => { + window.clearTimeout(timeout); + }; + }, [copied]); return ( ); diff --git a/src/core/client/framework/lib/relay/fetch.tsx b/src/core/client/framework/lib/relay/fetch.tsx index 70c647425e..6ebfb7fce0 100644 --- a/src/core/client/framework/lib/relay/fetch.tsx +++ b/src/core/client/framework/lib/relay/fetch.tsx @@ -74,29 +74,49 @@ export function useFetch( export function useImmediateFetch( fetch: Fetch>, variables: V, - refetch?: string + refetch?: any ): [R | null, boolean] { const fetcher = useFetch(fetch); - const [state, setState] = useState(null); - const [loading, setLoading] = useState(false); + const [state, setState] = useState<{ data: R | null; loading: boolean }>({ + data: null, + loading: false, + }); useEffect(() => { + let aborted = false; + async function doTheFetch() { - setState(null); - setLoading(true); - const value = await fetcher(variables); - - // TODO: Maybe we don't need this timeout? - setTimeout(() => { - setState(value); - setLoading(false); - }, 100 + 50 * Math.random()); + // Update the state by setting loading to true. + setState((s) => ({ ...s, loading: true })); + + try { + // Perform the fetch. + const data = await fetcher(variables); + if (aborted) { + // If we've aborted, we're either unmounting or a variable has changed, + // so don't bother finishing updating the state because another + // request is about to occur. + return; + } + + // Update the state with the data. + setState({ data, loading: false }); + } catch (err) { + // eslint-disable-next-line no-console + console.error("could not perform fetch", err); + + setState({ data: null, loading: false }); + } } void doTheFetch(); + + return () => { + aborted = true; + }; }, Object.values(variables).concat(isUndefined(refetch) ? [] : [refetch])); - return [state, loading]; + return [state.data, state.loading]; } /** diff --git a/src/core/client/stream/tabs/Comments/Comment/EditCommentForm/EditCommentFormContainer.tsx b/src/core/client/stream/tabs/Comments/Comment/EditCommentForm/EditCommentFormContainer.tsx index 8897f6b723..2c1e4e6037 100644 --- a/src/core/client/stream/tabs/Comments/Comment/EditCommentForm/EditCommentFormContainer.tsx +++ b/src/core/client/stream/tabs/Comments/Comment/EditCommentForm/EditCommentFormContainer.tsx @@ -1,5 +1,5 @@ import { CoralRTE } from "@coralproject/rte"; -import { clearLongTimeout, setLongTimeout } from "long-settimeout"; +import { clearLongTimeout, LongTimeout, setLongTimeout } from "long-settimeout"; import React, { Component } from "react"; import { graphql } from "react-relay"; @@ -73,7 +73,7 @@ function getMediaFromComment(comment: CommentData) { } export class EditCommentFormContainer extends Component { - private expiredTimer: any; + private expiredTimer?: LongTimeout; private intitialValues = { body: this.props.comment.body || "", media: getMediaFromComment(this.props.comment), @@ -93,7 +93,9 @@ export class EditCommentFormContainer extends Component { } public componentWillUnmount() { - clearLongTimeout(this.expiredTimer); + if (this.expiredTimer) { + clearLongTimeout(this.expiredTimer); + } } private updateWhenExpired() {