使用RealTime Firebase数据库的React App上的内存泄漏 [英] Memory Leak on React App that uses RealTime Firebase DataBase

查看:33
本文介绍了使用RealTime Firebase数据库的React App上的内存泄漏的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我不确定如何使用useEffect(),我一直在获取

I´m not sure how to use useEffect(), I keep getting

无法在已卸载的组件上执行React状态更新.这是无操作,但这表示您的应用程序中发生内存泄漏.修理,取消useEffect清理中的所有订阅和异步任务功能.登录

这是我的组件:

import React, { Component, useState, useEffect } from 'react';
import fire from '../fire';

import Sign from './sign';
import Dashboard from './dashboard';
import Map from './journey/map';

const Login = () => {


const [user, setUser ] = useState('');
const [email, setEmail] = useState('');
const [password, setPassword] = useState('');
const [emailError, setEmailError] = useState('');
const [passwordError, setPasswordError] = useState('');
const [hasAccount, setHasAccount] = useState(false);


const clearInputs = () => {
    setEmail('');
    setPassword('');
}

const clearErrors = () => {
    setEmailError('');
    setPasswordError('');
}

const handleLogin = () => {
    clearErrors();
    fire
        .auth()
        .signInWithEmailAndPassword(email, password)
        .catch(err => {
            switch(err.code){
                case 'auth/invalid-email':
                case 'auth/user-disabled':
                case 'auth/user-not-found':
                    setEmailError(err.message);
                    break;
                case 'auth/wrong-password':
                    setPasswordError(err.message);
                    break;
            }
        });
}

const handleSignUp = () => {
    clearErrors();
    fire
    .auth()
    .createUserWithEmailAndPassword(email, password)
    .catch(err => {
        switch(err.code){
            case 'auth/email-already-in-use':
            case 'auth/invalid-email':
                setEmailError(err.message);
                break;
            case 'auth/weak-password':
                setPasswordError(err.message);
                break;
        }
    });
    return 
}

const handleLogOut = () => {
    fire.auth().signOut();
};


const authListener = (user_id) => {
    user_id = '';
    fire.auth().onAuthStateChanged(user => {
        if(user) {
            clearInputs();
            setUser(user);
            user_id = user.email;
        } else {
            setUser('');
        }
    });
}

useEffect(() => {
    authListener();
    
}, []);

    return (
        
        <div>
            
            {user ? (
                <div>
                <Dashboard 
                handleLogOut={handleLogOut}
                user_id={user.email}
                />
                <Map 
                user_id={user.email}
                />
                </div>
            ) : (
                <Sign 
                email={email}
                setEmail={setEmail}
                password={password}
                setPassword={setPassword}
                handleLogin={handleLogin}
                handleSignUp={handleSignUp}
                hasAccount={hasAccount}
                setHasAccount={setHasAccount}
                emailError={emailError}
                passwordError={passwordError}
                />  
                
            )}
            
            
        

        </div>
    );

}

export default Login;

我正在使用Firebase身份验证.

I am using firebase authentication.

注意,只有当我进入子组件然后返回并退出应用程序时,才会发生内存泄漏.这是子组件.

Notes the memory leak happens only when I enter into the child component and then go back and log out of the app. here is the child component.

import React, { Component } from 'react';
import axios from 'axios';
import { Link } from "react-router-dom";

import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
import { faCaretSquareLeft } from '@fortawesome/free-solid-svg-icons'

import MapItem from '../mapItems';
import Card from './card';

class Cards extends Component {
constructor(props) {
    super(props);

    this.state = {
        journey_name: [],
        cards: [],
        data: [],
        hero: [],
        loading: true
    }

    this.cards = this.cards.bind(this);        
}


fetchCards = () => {

    axios.get('myapi').then(response => {
        console.log('fetchCards',response);
        this.setState({
            journey_name: response.data.journey_name,
            cards: response.data.cards,
        })
    }).catch(error => {
        console.log(`fetchCards error : ${error}`);
    }) 

}

fetchData = () => {
    axios.get('my api').then(response => {
        console.log('fetchdata',response);
        this.setState({
            data: response.data,
            hero: response.data.hero
        })
    }).catch(error => {
        console.log(`fetchData error : ${error}`);
    })
}

componentDidMount() {
    this.fetchCards();
    this.fetchData();

}

cards = () => {
    return (
        this.state.cards.map(card => {
            return (
                <Card
                    key={card.card_id}
                    card_name={card.card_name}
                    explanation={card.explanation}
                    image_url={card.image}
                    points={card.points}
                    reference={card.reference}
                />
            )
        })
    )
}


render() {

    return (
        <div className='cards-page'>
            <div className='cards-page__navbar'>
                <Link to='/'>
                    <FontAwesomeIcon icon={faCaretSquareLeft} />
                </Link>
                <MapItem
                    name={this.state.data.name}
                    level={this.state.hero.level}
                    points={this.state.hero.points}
                    class='cards-user'
                />
            </div>

            <div className='cards-rail'>
                {this.cards()}
            </div>

            <div className='footer'> by Johnattan M Angeles </div>
        </div>
    );
}
}

export default Cards;

推荐答案

尽管您可能应该取消订阅firebase onAuthStateChanged事件,但我认为您的问题可能与axios提取请求有关.如果他们后来在之后进行了解析,那么您已经离开子组件了,那么他们将更新已卸载组件的状态.当组件卸载时,您应该取消任何待处理的请求.

Though you should probably unsubscribe from the firebase onAuthStateChanged event, I think your issue may be with the axios fetch requests. If they later resolve after you've already navigated away from the child component then they are updating state of an unmounted component. You should cancel any pending requests when the component unmounts.

class Cards extends Component {
  constructor(props) {
    super(props);

    ...

    // Create cancel token & source
    const CancelToken = axio.CancelToken;
    this.source = CancelToken.source();
  }


  fetchCards = () => {
    axios.get(
      'myapi',
      { cancelToken: this.source.token }, // <-- pass cancel token W/ request
    ).then(response => {
      console.log('fetchCards',response);
      this.setState({
        journey_name: response.data.journey_name,
        cards: response.data.cards,
      })
    }).catch(error => {
      console.log(`fetchCards error : ${error}`);
    }) 

  }

  fetchData = () => {
    axios.get(
      'my api',
      { cancelToken: source.token }, // <-- pass cancel token W/ request
    ).then(response => {
      console.log('fetchdata',response);
      this.setState({
        data: response.data,
        hero: response.data.hero
      })
    }).catch(error => {
      console.log(`fetchData error : ${error}`);
    })
  }

  componentDidMount() {
    this.fetchCards();
    this.fetchData();
  }

  componentWillUnmount() {
    this.source.cancel('Operation cancelled by user'); // <-- cancel on unmount
  }

  ...
}

这篇关于使用RealTime Firebase数据库的React App上的内存泄漏的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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