React useEffect清理:如何以及何时使用它

前言

原文:https://dev.to/otamnitram/react-useeffect-cleanup-how-and-when-to-use-it-2hbm

译文如下。

React useEffect清理的语法

片段代码

您是否遇到以下错误? 消息很简单。我们正在尝试更改组件的状态,即使该组件已卸载且不可用。

Can't perform a React state update on an unmounted component. This is a no-op, but it indicates a memory leak in your application. To fix, cancel all subscriptions and asynchronous tasks in a useEffect cleanup function.
翻译过来,大致意思是:无法对已卸载的组件执行反应状态更新。这是一个no-op,但它表示应用程序中存在内存泄漏。若要修复,请取消useffect清除函数中的所有订阅和异步任务。

原因:组件卸载了,但是仍处于渲染数据状态(如:setState,useState)——最常见的原因是我们没有取消订阅websocket组件,或者在异步操作完成之前将其取消。

我们该如何解决?

useEffect挂钩中的清除功能。

useEffect挂钩的构建方式是,如果我们在方法内返回一个函数,则该函数将在取消关联组件时执行。这非常有用,因为我们可以使用它来消除不必要的行为或防止内存泄漏问题。

因此,如果我们要清理订阅,代码将如下所示:

useEffect(() => {
    API.subscribe()
    return function cleanup() {
        API.unsubscribe()
    }
})
 

不要更新已卸载组件的状态

一种常见的实现是在异步功能完成后更新组件状态。但是,如果在完成后卸载组件会怎样?如果我们不控制它,它将尝试设置状态。

在实际情况下,我在React Native上碰巧用户可以在进程结束之前离开屏幕。

在下面的示例中,我们有一个异步函数,该函数执行一些操作,并且在运行时,我要呈现“正在加载”消息。函数完成后,我将更改“正在加载”的状态并渲染另一条消息。

function Example(props) {
    const [loading, setloading] = useState(true)

    useEffect(() => {
        fetchAPI.then(() => {
            setloading(false)
        })
    }, [])

    return <div>{loading ? <p>loading...</p> : <p>Fetched!!</p>}</div>
}
 

但是,如果我们退出组件并且fetchAPI结束并设置了加载状态,这将提示开头提到的错误。因此,我们需要确保fetchAPI完成后仍可以装入该组件。

function Example(props) {
    const [loading, setloading] = useState(true)

    useEffect(() => {
        let mounted = true
        fetchAPI.then(() => {
            if (mounted) {
                setloading(false)
            }
        })

        return function cleanup() {
            mounted = false
        }
    }, [])

    return <div>{loading ? <p>loading...</p> : <p>Fetched!!</p>}</div>
}
 

这样,我们可以询问组件是否仍然安装。只需添加一个变量,如果我们卸下该变量,该变量将变为false。

额外:取消Axios请求

Axios带有取消选项,可以在请求结束之前完成请求。除了清除功能以外,这还可以防止内存泄漏。

useEffect(() => {
    const source = axios.CancelToken.source()

    const fetchUsers = async () => {
        try {
            await Axios.get('/users', {
                cancelToken: source.token,
            })
            // ...
        } catch (error) {
            if (Axios.isCancel(error)) {
            } else {
                throw error
            }
        }
    }

    fetchData()

    return () => {
        source.cancel()
    }
}, [])
 

结论

useEffect挂钩上还有很多其他清除函数的用法,但是我希望这可以使您更好地了解如何以及何时使用它。
请添加任何评论或建议,我将不胜感激。 

后续

React useEffect清理他说:

猜你喜欢

转载自blog.csdn.net/mChales_Liu/article/details/114066239
今日推荐