I am in the process of turning some older class-based react components into functional components. I came across a logout
class component (that I didn't code) that looks like this:
import React from 'react';
import {
Text,
} from 'react-native';
import { connect } from 'react-redux';
import { deauthenticateUser } from '../state/actions';
class LogoutScreen extends React.Component {
constructor() {
super();
}
async shouldComponentUpdate(nextProps, nextState) {
if(nextState.login == false) {
this.props.deauthenticateUser();
this.props.navigation.navigate('Auth');
}
return false;
}
componentDidMount() {
this.setState({login:false})
}
render() {
return (
<Text>Logging out...</Text>
)
}
}
// Redux Mapping
const mapStateToProps = state => {
return { ...state.User }
};
const mapDispatchToProps = dispatch => ({
deauthenticateUser: user => dispatch(deauthenticateUser(user)),
});
export default connect(mapStateToProps, mapDispatchToProps)(LogoutScreen);
I have refactored it into a functional component like so:
import React, { useEffect, useState } from 'react';
import {
Text,
} from 'react-native';
import { connect } from 'react-redux';
import { deauthenticateUser } from '../state/actions';
export const LogoutScreen = (props) => {
const [login, setLogin] = useState(false);
useEffect(() => {
if(login === false) {
props.deauthenticateUser();
props.navigation.navigate('Auth');
}
}, [login]);
return (
<Text>Logging out...</Text>
)
}
// Redux Mapping
const mapStateToProps = state => {
return { ...state.User }
};
const mapDispatchToProps = dispatch => ({
deauthenticateUser: user => dispatch(deauthenticateUser(user)),
});
export default connect(mapStateToProps, mapDispatchToProps)(LogoutScreen);
Question: is [login]
useful/necessary as a dependency in the useEffect()
hook in this case? What would behave differently if I didn't include it here?
CodePudding user response:
It is necessary to add login as a dependency in react hook useEffect in your code.
Check this plugin out : https://www.npmjs.com/package/eslint-plugin-react-hooks
CodePudding user response:
This is a very weird component - it is performing some critical business logic (logout) simply because it was rendered. That's very strange. Even the original component didn't really do anything - it gets rendered, it immediately sets the login state to false, and then it logs out the user and naigates somewhere.
I hate to say, but you shouldn't be using a component to do this. Instead you should use redux thunks/sagas/whatever to take care detecting when the app is trying to log out. Usually the user clicks a logout button or a session timer fires and updates the app state to something like { loggingOut: true }
. Then your thunk/saga/whatever picks up on this change and actually does the work of logging the user out and updating the current routes to redirect the user.
But I kind of expect that last paragraph to fall on deaf ears. Alas, you never needed the "login" state in either the original component or the new component. It's not doing anything and it only holds the value "false" - which is not state, it's just a variable with a constant value (eg. it never becomes "true"). Just get rid of it and log the user out immediately on render:
export const LogoutScreen = (props) => {
// the effect will only run once (see the empty array as the second arg)
useEffect(() => {
props.deauthenticateUser();
props.navigation.navigate('Auth');
}, []);
return (
<Text>Logging out...</Text>
)
}
And for completeness, here's what your original component should have looked like:
class LogoutScreen extends React.Component {
componentDidMount() {
this.props.deauthenticateUser();
this.props.navigation.navigate('Auth');
}
render() {
return (
<Text>Logging out...</Text>
)
}
}