chore: useAbortableEffect

This commit is contained in:
EnixCoda 2022-10-26 21:05:46 +08:00
parent 5417fb4496
commit 36d6421f6e
3 changed files with 24 additions and 25 deletions

View file

@ -1,9 +1,9 @@
import { useConfigs } from 'containers/ConfigsContext'
import { platform } from 'platforms'
import { useCallback, useState } from 'react'
import { useAbortableEffect } from 'utils/hooks/useAbortableEffect'
import { useCatchNetworkError } from 'utils/hooks/useCatchNetworkError'
import { useLoadedContext } from 'utils/hooks/useLoadedContext'
import { useSequentialEffect } from 'utils/hooks/useSequentialEffect'
import { VisibleNodesGenerator } from 'utils/VisibleNodesGenerator'
import { SideBarStateContext } from '../../../containers/SideBarState'
@ -17,12 +17,12 @@ export function useVisibleNodesGenerator(metaData: MetaData | null) {
const setStateContext = useLoadedContext(SideBarStateContext).onChange
// Only run when metadata or accessToken changes
useSequentialEffect(
useAbortableEffect(
useCallback(
shouldAbort => {
signal => {
catchNetworkErrors(async () => {
if (!metaData) return
if (shouldAbort()) return
if (signal.aborted) return
setStateContext('tree-loading')
const { userName, repoName, branchName } = metaData
@ -36,7 +36,7 @@ export function useVisibleNodesGenerator(metaData: MetaData | null) {
true,
config.accessToken,
)
if (shouldAbort()) return
if (signal.aborted) return
setStateContext('tree-rendering')

View file

@ -0,0 +1,19 @@
import { useEffect } from 'react'
/**
* This effect addresses such a problem:
* the later effect ends earlier than the previous one, and the previous effect overlaps later effect's result.
*/
export function useAbortableEffect(
effect: (shouldAbort: AbortSignal) => (() => void | undefined) | void,
) {
useEffect(() => {
const abortController = new AbortController()
// The previous effect should stop running if the signal indicates should abort
const defect = effect(abortController.signal)
return () => {
abortController.abort()
defect?.()
}
}, [effect])
}

View file

@ -1,20 +0,0 @@
import { useEffect } from 'react'
/**
* This effect addresses such a problem:
* the later effect ends earlier than the previous one, and the previous effect overlaps later effect's result.
*/
export function useSequentialEffect(
effect: (shouldAbort: () => boolean) => (() => void | undefined) | void,
) {
useEffect(() => {
// The previous effect should stop running if shouldAbort returns true.
let end = false
const shouldAbort = () => end
const defect = effect(shouldAbort)
return () => {
end = true
defect?.()
}
}, [effect])
}