反应-在获取数据并设置该数据的状态后如何清理useEffect()?

问题描述 投票:1回答:1

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

警告:无法在已卸载的组件上执行React状态更新。这是空操作,但它表明应用程序中发生内存泄漏。要修复,请取消使用useEffect清理功能中的所有订阅和异步任务。

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

这是我的代码:

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" /> }/>
    )
}

感谢您的任何帮助:)

更新#2:

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

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>
    )
}

更新#1:

好,所以我弄清楚了问题所在。重定向用户似乎引起了一些问题,因此我没有使用“重定向”,而是使用了该组件进行登录,并且警告消失了。但是,现在当我渲染新组件时,并不需要我进入'/ login'。

这是现在的更新代码:

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

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();
                console.log(data);
                setUser(data.session.passport.user);

            } catch (error) {
                console.log(error);
            }
        }

        fetchUser();
    }, [])

    return (
        <Route { ...rest } render={ () => user ? <Component /> : <UserLogin /> } />
    )
}

reactjs fetch react-hooks use-effect
1个回答
1
投票

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

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" /> }/>
    )
}
© www.soinside.com 2019 - 2024. All rights reserved.