From 6565bfb917d568e5d88c7318c27f00b15bd20022 Mon Sep 17 00:00:00 2001 From: morrys Date: Tue, 12 Dec 2023 12:55:31 +0100 Subject: [PATCH] add abort controller --- .../src/components/TodoList.tsx | 48 ++++++-------- .../src/relay/createRelayEnvironment.ts | 66 +++++++++++++------ 2 files changed, 67 insertions(+), 47 deletions(-) diff --git a/examples/relay-hook-example/pagination-nextjs-ssr/src/components/TodoList.tsx b/examples/relay-hook-example/pagination-nextjs-ssr/src/components/TodoList.tsx index c6d0c40e..8800017f 100644 --- a/examples/relay-hook-example/pagination-nextjs-ssr/src/components/TodoList.tsx +++ b/examples/relay-hook-example/pagination-nextjs-ssr/src/components/TodoList.tsx @@ -55,15 +55,9 @@ const StyledList = styled.ul` const fragmentSpecs = graphql` fragment TodoList_user on User - @refetchable(queryName: "UserFragmentRefetchQuery") - @argumentDefinitions( - first: { type: Int } - after: { type: String } - last: { type: Int } - before: { type: String } - ) { - todos(first: $first, after: $after, before: $before, last: $last) - @connection(key: "TodoList_todos") { + @refetchable(queryName: "UserFragmentRefetchQuery") + @argumentDefinitions(first: { type: Int }, after: { type: String }, last: { type: Int }, before: { type: String }) { + todos(first: $first, after: $after, before: $before, last: $last) @connection(key: "TodoList_todos") { edges { node { id @@ -87,13 +81,8 @@ const fragmentSpecs = graphql` const fragmentTableSpecs = graphql` fragment TodoListTable_user on User - @refetchable(queryName: "UserFragmentRefetchTableQuery") - @argumentDefinitions( - first: { type: Int } - after: { type: String } - last: { type: Int } - before: { type: String } - ) { + @refetchable(queryName: "UserFragmentRefetchTableQuery") + @argumentDefinitions(first: { type: Int }, after: { type: String }, last: { type: Int }, before: { type: String }) { todos(first: $first, after: $after, before: $before, last: $last) @connection(key: "TodoList_todos", handler: "connection_table") { edges { @@ -140,13 +129,15 @@ export const TodoList = (props: Props): JSX.Element => { ); const { todos, totalCount } = user || {}; - + const mount = React.useRef(true); React.useEffect(() => { - console.log("mount list") + mount.current = true; + console.log('mount list'); return () => { - console.log("dismout list") - } - }, []) + mount.current = false; + console.log('dismout list'); + }; + }, []); const refresh = useCallback((): Disposable => { const onComplete = (): void => { setRowsPerPage(rowsPerPage); @@ -168,15 +159,18 @@ export const TodoList = (props: Props): JSX.Element => { const isLoading = props.isLoading || refetchLoading || ((paginated || scroll) && (isLoadingPrevious || isLoadingNext)); - - console.log("loading", props.isLoading, refetchLoading, isLoadingPrevious, isLoadingNext) + + console.log('loading', props.isLoading, refetchLoading, isLoadingPrevious, isLoadingNext); const loadMore = useCallback(() => { // Don't fetch again if we're already loading the next page - if (isLoading) { + if (isLoading || !mount.current) { return; } - console.log("load") - loadNext(1); + const disposable = loadNext(1); + return () => { + console.log('dissssss'); + disposable.dispose(); + }; }, [isLoading, loadNext]); const handleChangePage = useCallback( @@ -224,7 +218,7 @@ export const TodoList = (props: Props): JSX.Element => { }, [environment, user, onCompleted], ); - console.log("list render", scroll, hasNext, isLoading) + console.log('list render', scroll, hasNext, isLoading); return ( diff --git a/examples/relay-hook-example/pagination-nextjs-ssr/src/relay/createRelayEnvironment.ts b/examples/relay-hook-example/pagination-nextjs-ssr/src/relay/createRelayEnvironment.ts index df493678..e3b671c2 100644 --- a/examples/relay-hook-example/pagination-nextjs-ssr/src/relay/createRelayEnvironment.ts +++ b/examples/relay-hook-example/pagination-nextjs-ssr/src/relay/createRelayEnvironment.ts @@ -12,27 +12,53 @@ function sleep(ms): Promise { function fetchQuery(operation, variables, _cacheConfig, _uploadables): any { const endpoint = 'http://localhost:3000/graphql'; - return Observable.create((sink) => { - sleep(2000).then(() => fetch(endpoint, { - method: 'POST', - headers: { - Accept: 'application/json', - 'Content-Type': 'application/json', - }, // Add authentication and other headers here - body: JSON.stringify({ - query: operation.text, // GraphQL text from input - variables, - }), - }).then(response => response.json()) - .then(data => { - if (data.errors) { - sink.error(data.errors); - return - } - sink.next(data); - sink.complete(); - })); + const controller = new AbortController(); + let doAbort = true; + const observer = Observable.create((sink) => { + sleep(2).then(() => + fetch(endpoint, { + signal: controller.signal, + method: 'POST', + headers: { + Accept: 'application/json', + 'Content-Type': 'application/json', + }, // Add authentication and other headers here + body: JSON.stringify({ + query: operation.text, // GraphQL text from input + variables, + }), + }) + .then((response) => { + doAbort = false; + return response.json(); + }) + .then((data) => { + console.log('end fetch', data); + if (data.errors) { + sink.error(data.errors); + return; + } + sink.next(data); + sink.complete(); + }) + .catch((e) => { + sink.error(e); + }), + ); + return (): void => { + if (doAbort) { + console.log('aborttt'); + controller.abort('unsubscribe'); + } + }; }); + /*observer.subscribe({ + unsubscribe: (): void => { + console.log('aborttt'); + controller.abort(); + }, + });*/ + return observer; } type InitProps = {