reactjs - 清理 useEffect 的正确方法
问题描述
我有useEffect
回调,这给了我一个错误:
警告:无法对未安装的组件执行 React 状态更新。这是一个空操作,但它表明您的应用程序中存在内存泄漏。要解决此问题,请在 useEffect 清理函数中取消所有订阅和异步任务。
这是我的代码:
import React, {useEffect, useState} from 'react'
import { useTranslation } from 'react-i18next'
import firebase from 'firebase/app'
import '../firebase'
import Input from '../Components/Input'
import Button from '../Components/Button'
import { useHistory, useParams } from 'react-router-dom'
import { connect } from 'react-redux'
import { isAuth } from '../redux/actions/session/isAuth'
import Header from '../Modules/Header'
import Loader from '../Components/Loader'
import logo from '../media/logo/seanor_logo.svg'
let db = firebase.firestore()
const Login = ({setIsAuth, agencyData, userData, userUID, isAuth}) => {
const { t } = useTranslation()
let history = useHistory()
let { agency } = useParams()
// Change document title
document.title = `${t('login')}`
const [loading, setLoading] = useState(false)
// Input states
const [email, setEmail] = useState('')
const [password, setPassword] = useState('')
const [error, setError] = useState(false)
const [agencyErr, setAgencyErr] = useState(false)
useEffect( () => {
const checkUserType = () => {
// Check is user logged in and redirects to dashboard
if (userData !== null && isAuth) {
if (userData.type === 'employee') {
history.push(`/${agency}/dashboard/${userUID}`)
} else if (userData.type === 'crewagency') {
history.push(`/${agency}/crew-dashboard/`)
} else if ( userData.type === 'keyagency') {
history.push(`/${agency}/key-dashboard/`)
}
}
}
return () => checkUserType()
}, [agency, history, userData, userUID, isAuth])
const submit = () => {
setAgencyErr(false)
setLoading(true)
firebase.auth()
.signInWithEmailAndPassword(email, password)
.then(res => {
let resData = JSON.stringify(res.user)
resData = JSON.parse(resData)
let uid = resData.uid
// Check is usere belongs to agency
db.collection('users').doc(uid).get()
.then( res => {
let resData = JSON.stringify(res.data())
resData = JSON.parse(resData)
if (resData.data.agencyId === agency) {
// Check user type and redirect to dashboar by type
if (resData.data.type === 'employee') {
history.push(`/${agency}/dashboard/${uid}`)
} else if (resData.data.type === 'crewagency') {
history.push(`/${agency}/crew-dashboard`)
} else if ( resData.data.type === 'keyagency') {
history.push(`/${agency}/key-dashboard`)
}
} else {
firebase.auth().signOut()
setAgencyErr(true)
}
setLoading(false)
})
.catch(err => console.log('User info error', err))
setIsAuth(true)
})
.catch(err => {
console.log('Login error: ', err.message)
setError(true)
setLoading(false)
})
}
return (
<div>
{loading && <Loader />}
<Header />
<div className='login'>
<div className='login__box'>
<div className='login__logo'>
<img src={logo} alt='logo' />
</div>
<div className='login__box-title'>
<h2>{t('loginToCrewManager')}</h2>
</div>
<div className='login__input'>
<div className='login__input-label'>
{t('email')}
</div>
<Input
type='email'
handleInput={(value) => setEmail(value)}
/>
</div>
<div className='login__input'>
<div className='login__input-label'>
{t('password')}
</div>
<Input
type='password'
handleInput={(value) => setPassword(value)}
/>
</div>
{error &&
<div className='error'>
{t('loginError')}
</div>}
{agencyErr &&
<div className='error'>
{t('agencyErrorLogin')}
</div>}
<div className='login__submit'>
<Button
text='login'
handleClick={() => submit()}
/>
</div>
<div className='login__registration'>
<a href={`/${agency}/reset-password`}>{t('resetPasswordLogin')}</a>
</div>
<div className='login__registration'>
<a href={`/${agency}/registration`}>{t('newUserRegistration')}</a>
</div>
</div>
</div>
</div>
)
}
const mapStateToProps = state => {
return {
agencyData: state.agencyDataRed.obj,
isAuth: state.isAuthRed.bool
}
}
const mapDispatchToProps = dispatch => {
return {
setIsAuth: bool => dispatch(isAuth(bool))
}
}
export default connect(mapStateToProps, mapDispatchToProps)(Login)
也许我不明白清理功能?我的错误在哪里?
解决方案
我认为问题出在您的submit
函数中,并且您states
在更改 url 后设置了一个。我移动setLoading(false)
了一点,试试这个:
const submit = () => {
setAgencyErr(false);
setLoading(true);
firebase
.auth()
.signInWithEmailAndPassword(email, password)
.then((res) => {
let resData = JSON.stringify(res.user);
resData = JSON.parse(resData);
let uid = resData.uid;
// Check is usere belongs to agency
db.collection("users")
.doc(uid)
.get()
.then((res) => {
let resData = JSON.stringify(res.data());
resData = JSON.parse(resData);
if (resData.data.agencyId === agency) {
// Check user type and redirect to dashboar by type
if (resData.data.type === "employee") {
history.push(`/${agency}/dashboard/${uid}`);
} else if (resData.data.type === "crewagency") {
history.push(`/${agency}/crew-dashboard`);
} else if (resData.data.type === "keyagency") {
history.push(`/${agency}/key-dashboard`);
}
} else {
firebase.auth().signOut();
setAgencyErr(true);
setLoading(false); //<=== HERE
}
})
.catch((err) => console.log("User info error", err));
setIsAuth(true);
})
.catch((err) => {
console.log("Login error: ", err.message);
setError(true);
setLoading(false);
});
};
setIsAuth(true)
是需要搬到正确位置的候选人之一
推荐阅读
- algorithm - Mandelbrot 集的内部距离估计算法
- performance - SpyderKernelApp WARNING No such comm in windows 10 on spyder3 ide
- sql - 没有参数时从表中获取所有数据的 SQL 查询
- javascript - 删除文件名的扩展名并使用正则表达式 vscode 片段将 camelCase 转换为蛇形大小写?
- flutter - 包含特定文档的 SreamProvider
- hyperledger-fabric - 将客户注册信息链下存储在超级账本结构中的最佳方式是什么
- reactjs - 如何将 Props 传递到 React Router 6 以便可以在 mapStateToProps(state,ownProps) 中访问它?
- flutter - Flutter Stacking children in a Stack
- laravel - Twilio 从 MediaStream 收到错误
- javascript - 为什么在 React 的 useEffect 中返回时间戳值会变成 bool?