Added component unmount cleanup

This commit is contained in:
Dmitriy Shishkov 2023-07-11 14:43:08 +03:00
parent 960ad7ce0d
commit 8fc85e415f
Signed by: dm1sh
GPG Key ID: 027994B0AA357688
4 changed files with 51 additions and 11 deletions

View File

@ -1,15 +1,30 @@
import { useState } from "react"
import { useEffect, useRef, useState } from "react"
import { API_URL } from "../../config"
const useAddAnnouncement = () => {
const [status, setStatus] = useState("Опубликовать")
const timerIdRef = useRef()
const abortControllerRef = useRef()
const doAdd = async (formData) => {
setStatus(true)
if (status === "Загрузка") {
abortControllerRef.current?.abort()
setStatus("Отменено")
timerIdRef.current = setTimeout(() => setStatus("Опубликовать"), 3000)
return
}
setStatus("Загрузка")
const abortController = new AbortController()
abortControllerRef.current = abortController
try {
const res = await fetch(API_URL + "/announcement", {
method: 'PUT',
body: formData,
signal: abortController.signal
})
const data = await res.json()
@ -21,9 +36,17 @@ const useAddAnnouncement = () => {
} catch (err) {
setStatus(err.message ?? err)
setTimeout(() => setStatus("Опубликовать"), 10000)
timerIdRef.current = setTimeout(() => setStatus("Опубликовать"), 10000)
}
}
}
useEffect(() => {
const abortController = abortControllerRef.current
return () => {
clearTimeout(timerIdRef.current)
abortController?.abort()
}
})
return {doAdd, status}
}

View File

@ -10,7 +10,7 @@ function useBook(id) {
const [status, setStatus] = useState('')
const handleBook = () => {
const token = getToken() || "Test"
const token = getToken()
if (token) {
setStatus("Загрузка")

View File

@ -1,12 +1,22 @@
import { useEffect, useState } from "react"
import { useEffect, useRef, useState } from "react"
import { isAborted } from '../../utils'
const useFetch = (url, params, initialData) => {
const [data, setData] = useState(initialData)
const [loading, setLoading] = useState(true)
const [error, setError] = useState("")
const abortControllerRef = useRef(null)
useEffect(() => {
fetch(url, params)
if (abortControllerRef.current) {
abortControllerRef.current.abort()
}
const abortController = new AbortController()
abortControllerRef.current = abortController
fetch(url, { ...params, signal: abortControllerRef.current.signal })
.then(res => {
if (!res.ok) {
switch (res.status) {
@ -27,16 +37,21 @@ const useFetch = (url, params, initialData) => {
setLoading(false)
})
.catch(err => {
setError("Ошибка сети")
if (!isAborted(err)) {
setError("Ошибка сети")
}
setLoading(false)
if (import.meta.env.DEV) {
console.log(url, params, err)
}
})
return () => abortControllerRef.current.abort()
}, [url, params])
return { data, loading, error }
return { data, loading, error, abort: abortControllerRef.current?.abort }
}
export default useFetch

View File

@ -5,6 +5,8 @@ const removeNull = (obj) => Object.fromEntries(
key,
value === Object(value) ? removeNull(value) : value,
]),
);
)
export { removeNull }
const isAborted = (err) => err.name == 'AbortError'
export { removeNull, isAborted }