Reactjs 使用实时Firebase数据库的React应用程序内存泄漏

Reactjs 使用实时Firebase数据库的React应用程序内存泄漏,reactjs,firebase-realtime-database,memory-leaks,axios,Reactjs,Firebase Realtime Database,Memory Leaks,Axios,我不知道如何使用useffect(),我一直在 无法对未安装的组件执行React状态更新。这是 无操作,但表示应用程序内存泄漏。要解决, 取消useEffect清理中的所有订阅和异步任务 功能。 登录时 以下是我的组件: import React, { Component, useState, useEffect } from 'react'; import fire from '../fire'; import Sign from './sign'; import Dashboard fro

我不知道如何使用useffect(),我一直在

无法对未安装的组件执行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;
import React,{Component,useState,useffect}来自'React';
从“../fire”导入火;
从“./Sign”导入符号;
从“/Dashboard”导入仪表板;
从“./旅程/地图”导入地图;
常量登录=()=>{
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);
常量clearInputs=()=>{
setEmail(“”);
设置密码(“”);
}
常量clearErrors=()=>{
setEmailError(“”);
setPasswordError(“”);
}
常量handleLogin=()=>{
clearErrors();
火
.auth()
.使用电子邮件和密码登录(电子邮件、密码)
.catch(错误=>{
开关(错误代码){
案例“验证/无效电子邮件”:
案例“已禁用身份验证/用户”:
案例“未找到身份验证/用户”:
setEmailError(错误消息);
打破
案例“身份验证/密码错误”:
setPasswordError(错误消息);
打破
}
});
}
常量handleSignUp=()=>{
clearErrors();
火
.auth()
.createUserWithEmailAndPassword(电子邮件,密码)
.catch(错误=>{
开关(错误代码){
案例“身份验证/电子邮件已在使用中”:
案例“验证/无效电子邮件”:
setEmailError(错误消息);
打破
案例“身份验证/弱密码”:
setPasswordError(错误消息);
打破
}
});
返回
}
常量handleLogOut=()=>{
fire.auth().signOut();
};
const authListener=(用户id)=>{
用户id=“”;
fire.auth().onAuthStateChanged(用户=>{
如果(用户){
clearInputs();
setUser(用户);
user_id=user.email;
}否则{
setUser(“”);
}
});
}
useffect(()=>{
authListener();
}, []);
返回(
{用户(
) : (
)}
);
}
导出默认登录;
我正在使用firebase身份验证

注意只有当我进入子组件,然后返回并注销应用程序时,才会发生内存泄漏。 下面是子组件

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;
import React,{Component}来自'React';
从“axios”导入axios;
从“react router dom”导入{Link};
从“@fortawesome/react fontawesome”导入{FontAwesomeIcon}
从“@fortawesome/free solid svg icons”导入{faCaretSquareLeft}
从“../mapItems”导入MapItem;
从“./卡”导入卡;
类卡扩展组件{
建造师(道具){
超级(道具);
此.state={
旅程名称:[],
卡片:[],
数据:[],
英雄:[],,
加载:正确
}
this.cards=this.cards.bind(this);
}
fetchCards=()=>{
get('myapi')。然后(响应=>{
console.log('fetchCards',响应);
这是我的国家({
旅程名称:response.data.旅程名称,
卡片:response.data.cards,
})
}).catch(错误=>{
log(`fetchCards error:${error}`);
}) 
}
fetchData=()=>{
get('MyAPI')。然后(响应=>{
log('fetchdata',响应);
这是我的国家({
数据:response.data,
英雄:response.data.hero
})
}).catch(错误=>{
log(`fetchData error:${error}`);
})
}
componentDidMount(){
这是fetchCards();
这是fetchData();
}
卡片=()=>{
返回(
this.state.cards.map(card=>{
返回(
)
})
)
}
render(){
返回(
{this.cards()}
作者:约翰纳坦·M·洛杉矶
);
}
}
导出默认卡;

虽然您可能应该取消订阅firebase onAuthStateChanged事件,但我认为您的问题可能与axios fetch请求有关。如果它们在您导航离开子组件后解决,则它们将更新未安装组件的状态。您应该在组件卸载时删除所有挂起的请求

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
  }

  ...
}
类卡扩展组件{
建造师(道具){
超级(道具);
...
//创建取消令牌和源
const CancelToken=axio.CancelToken;
this.source=CancelToken.source();
}
fetchCards=()=>{
axios.get(
“myapi”,
{cancelToken:this.source.token},//{
console.log('fetchCards',响应);
这是我的国家({
旅程名称:response.data.旅程名称,
卡片:response.data.cards,
})
}).catch(错误=>{
log(`fetchCards error:${error}`);
}) 
}
fetchData=()=>{
axios.get(
“我的api”,
{cancelToken:source.token},//{
log('fetchdata',响应);
这是我的国家({
数据:response.data,
英雄:response.data.hero
})
}).catch(错误=>{
log(`fetchData error:${error}`);
})
}
componentDidMount(){
这是fetchCards();
这是fetchData();
}
组件将卸载(){

this.source.cancel('Operation cancelled by user');//尽管您可能应该从firebase取消订阅