React - 在获取数据并使用该数据设置状态后,您如何清理 useEffect()? [英] React - How do you cleanup useEffect() after fetching data and setting a state with that data?

查看:32
本文介绍了React - 在获取数据并使用该数据设置状态后,您如何清理 useEffect()?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用钩子 useEffect 向我的服务器发出提取请求,但我不断收到此警告:

警告:无法对卸载的组件执行 React 状态更新.这是一个空操作,但它表明您的应用程序中存在内存泄漏.要修复,请取消 useEffect 清理函数中的所有订阅和异步任务.

我了解此警告的原因,但我该如何清理它?我尝试了本文中建议的方法但没有成功:https://dev.to/pallymore/clean-up-async-requests-in-useeffect-hooks-90h

这是我的代码:

import React, { useEffect, useState } from 'react';从'react-router-dom'导入{重定向,路由};导出默认函数 ProtectedRoute({ component: Component, ...rest }) {const [用户,setUser] = useState('');useEffect(() => {const fetchUser = async() =>{尝试 {const response = await fetch('http://localhost:5000/user', {凭据:'包括'});const 数据 = 等待 response.json();setUser(data.session.passport.user);} 捕捉(错误){控制台日志(错误);}}fetchUser();返回 () =>{//做一些清理}}, [])返回 (<Route { ...rest } render={ () =>用户?<组件/>:<重定向到=/登录";/>}/>)}

感谢任何帮助:)

更新:感谢以下 Tony Nguyen 的解决方案,这是我的工作代码:

import React, { useEffect, useState } from 'react';从'react-router-dom'导入{重定向,路由};从'./Loading'导入加载;从'./Error'导入错误;导出默认函数 ProtectedRoute({ component: Component, ...rest }) {const [用户,setUser] = useState('');const [ fetchingUser, setFetchingUser ] = useState(true);const [ noError, setNoError ] = useState(true);useEffect(() => {const fetchUser = async() =>{尝试 {const response = await fetch('http://localhost:5000/user', {凭据:'包括'});如果(获取用户){const 数据 = 等待 response.json();setUser(data.session.passport.user);}setFetchingUser(false);} 抓住 {设置无错误(假);}}fetchUser();}, [])返回 (<div><Route { ...rest } render={ () =>{ if (!noError) return } }/><Route { ...rest } render={ () =>{ if (fetchingUser && noError) return <Loading/>} }/><Route { ...rest } render={ () =>{ if (user && !fetchingUser && noError) return <Component/>} }/><Route { ...rest } render={ () =>{ if (!user && !fetchingUser && noError) return 

)}

解决方案

你的第一段代码没问题,只是需要一些修改,即添加 fetchingUser 让组件知道你正在获取用户,不要重定向

import React, { useEffect, useState } from 'react';从'react-router-dom'导入{重定向,路由};导出默认函数 ProtectedRoute({ component: Component, ...rest }) {//添加 fetchingUser 状态,默认为 trueconst [ fetchingUser, setFetchingUser ] = useState(true);const [用户,setUser] = useState('');useEffect(() => {const fetchUser = async() =>{尝试 {const response = await fetch('http://localhost:5000/user', {凭据:'包括'});const 数据 = 等待 response.json();setUser(data.session.passport.user);//这里 setFetching 是假的设置获取用户(假)} 捕捉(错误){//您可以在此处创建错误状态并设置错误控制台日志(错误);}}fetchUser();返回 () =>{//做一些清理}}, [])//将 fetchingUser 添加到条件中//如果获取显示加载组件,您可以做得更好//如果错误显示错误组件//如果没有获取错误并且让用户显示用户组件//如果没有获取不是错误并且不是用户重定向到登录返回 (<Route { ...rest } render={ () =>用户&&!fetchingUser ?<组件/>:<重定向到=/登录"/>}/>)}

I am making a fetch request to my server with the hook useEffect, and I keep getting this warning:

Warning: 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.

I understand the reason for this warning, but how do I clean it up? I have tried methods suggested in this article with no luck: https://dev.to/pallymore/clean-up-async-requests-in-useeffect-hooks-90h

Here is my code:

import React, { useEffect, useState } from 'react';
import { Redirect, Route } from 'react-router-dom';

export default function ProtectedRoute({ component: Component, ...rest }) {
    
    const [ user, setUser ] = useState('');

    useEffect(() => {
        const fetchUser = async () => {
            try {
                const response = await fetch('http://localhost:5000/user', {
                    credentials: 'include'
                });

                const data = await response.json();

                setUser(data.session.passport.user);
            
            } catch (error) {
                console.log(error);
            }
        }

        fetchUser();

        return () => {
         // Do some cleanup   
        }
    }, [])

    return (
         <Route { ...rest } render={ () => user ? <Component /> : <Redirect to="/login" /> }/>
    )
}

Any help is appreciated :)

UPDATE: Thanks to Tony Nguyen's solution below, here is my working code:

import React, { useEffect, useState } from 'react';
import { Redirect, Route } from 'react-router-dom';

import Loading from './Loading';
import Error from './Error';

export default function ProtectedRoute({ component: Component, ...rest }) {
    
    const [ user, setUser ] = useState('');
    const [ fetchingUser, setFetchingUser ] = useState(true);
    const [ noError, setNoError ] = useState(true);

    useEffect(() => {
        const fetchUser = async () => {
            try {
                const response = await fetch('http://localhost:5000/user', {
                    credentials: 'include'
                });

                if (fetchingUser) {
                    const data = await response.json();
                    setUser(data.session.passport.user);
                }

                setFetchingUser(false);

            } catch {
                setNoError(false);
            }
        }

        fetchUser();
    }, [])

    return (

        <div>
            <Route { ...rest } render={ () => { if (!noError) return <Error />} }/>
            <Route { ...rest } render={ () => { if (fetchingUser && noError) return <Loading />} }/>
            <Route { ...rest } render={ () => { if (user && !fetchingUser && noError) return <Component />} }/>
            <Route { ...rest } render={ () => { if (!user && !fetchingUser && noError) return <Redirect to="/login" />} }/>
        </div>
    )
}

解决方案

Your first piece of code is ok just need some modification that is adding fetchingUser to let the component know you fetching user, do not redirect

import React, { useEffect, useState } from 'react';
import { Redirect, Route } from 'react-router-dom';

export default function ProtectedRoute({ component: Component, ...rest }) {
     // add fetchingUser state with defaut is true
     const [ fetchingUser, setFetchingUser ] = useState(true);
    const [ user, setUser ] = useState('');

    useEffect(() => {
        const fetchUser = async () => {
            try {
                const response = await fetch('http://localhost:5000/user', {
                    credentials: 'include'
                });

                const data = await response.json();
                setUser(data.session.passport.user);
                // setFetching is false here
                setFetchingUser(false)

            } catch (error) {
                // You can create an error state and set error here
                console.log(error);
            }
        }

        fetchUser();

        return () => {
         // Do some cleanup   
        }
    }, [])
  
  
  // add fetchingUser into conditions
  // You can do better job that is if fetching show Loading component
  // If error show error component
  // if not fetching not error and have user show user component
  // if not fetching not error and not user redirect to login
    return (
         <Route { ...rest } render={ () => user && !fetchingUser ? <Component /> : <Redirect to="/login" /> }/>
    )
}

这篇关于React - 在获取数据并使用该数据设置状态后,您如何清理 useEffect()?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆