Reactjs 使用实时Firebase数据库的React应用程序内存泄漏
我不知道如何使用useffect(),我一直在 无法对未安装的组件执行React状态更新。这是 无操作,但表示应用程序内存泄漏。要解决, 取消useEffect清理中的所有订阅和异步任务 功能。 登录时 以下是我的组件: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
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取消订阅