I encountered this error when trying to switch my bootcamp project code from class components to stateful functional components:
TypeError: Cannot read property 'user' of undefined
(anonymous function)
C:/Proiect curs react/src/pages/Login/Login.jsx:35
32 | // }
33 |
34 | useEffect((prevProps) => {
> 35 | if (props.user !== prevProps.user) {
| ^ 36 | props.history.push("/");
37 | }
38 | }, [props.user, props.history]);
This occured in the Login component which is responsable for displaying an option to connect via Google - using a firebase service, and redirecting to the home page, which is what the useEffect is trying to do.
Commented below in the code is the code of the componentDidUpdate methond that did just that while the component was a class.
import React, { useEffect } from "react";
import { Link } from "react-router-dom";
import Logo from "../../assets/images/logo.png";
import { ReactComponent as Google } from "../../assets/icons/google.svg";
import "./Login.css";
import { connect } from "react-redux";
import { loginUser } from "../../redux/actions/user";
const Login = (props) => {
// componentDidUpdate(prevProps) {
// if (this.props.user !== prevProps.user) {
// this.props.history.push('/');
// }
// }
useEffect((prevProps) => {
if (props.user !== prevProps.user) {
props.history.push("/");
}
}, [props.user, props.history]);
return (
<div className="login-page">
<Link to="/">
<img src={Logo} alt="logo" className="mb-5" />
</Link>
<h1 className="h2">Login</h1>
<p>Alege providerul cu care vrei să vrei să te loghezi:</p>
<button
className="btn btn-outline-dark d-flex align-items-center"
onClick={() => props.signInWithGoogle()}
>
<Google className="w-50 mr-3" />
<span className="text-nowrap">Loghează-te cu Google</span>
</button>
</div>
);
};
function mapStateToProps(state) {
return {
user: state.user.data,
};
}
function mapDispatchToProps(dispatch) {
return {
signInWithGoogle: () => dispatch(loginUser()),
};
}
export default connect(mapStateToProps, mapDispatchToProps)(Login);
Also, below is the link to the github repository that holds the whole app.
https://github.com/vradu007/radu-shop
Please let me know if you can tell me what I did wrong - I have not studied hooks at my bootcamp, but I am using them at work, and I have been trying to get a grasp of it looking online. Thank you!
Edit: Using that answer, I got the following error:
./src/pages/Login/Login.jsx
Line 10:17: React Hook "useRef" is called in function "getPrevious" which is neither a React function component or a custom React Hook fun
ction react-hooks/rules-of-hooks
Line 11:5: React Hook "useEffect" is called in function "getPrevious" which is neither a React function component or a custom React Hook
function react-hooks/rules-of-hooks
The error is reproduced whether or not I import useRef. The current component is looking like this:
import React, { useEffect, useRef } from "react";
import { Link } from "react-router-dom";
import Logo from "../../assets/images/logo.png";
import { ReactComponent as Google } from "../../assets/icons/google.svg";
import "./Login.css";
import { connect } from "react-redux";
import { loginUser } from "../../redux/actions/user";
function getPrevious(value) {
const ref = useRef();
useEffect(() => {
ref.current = value;
});
return ref.current;
}
const Login = (props) => {
// componentDidUpdate(prevProps) {
// if (this.props.user !== prevProps.user) {
// this.props.history.push('/');
// }
// }
const { user, history } = props;
const previous = getPrevious({ user, history });
useEffect(
(prevProps) => {
if (props.user !== previous.user) {
props.history.push("/");
}
},
[props.user, props.history]
);
return (
<div className="login-page">
<Link to="/">
<img src={Logo} alt="logo" className="mb-5" />
</Link>
<h1 className="h2">Login</h1>
<p>Alege providerul cu care vrei să vrei să te loghezi:</p>
<button
className="btn btn-outline-dark d-flex align-items-center"
onClick={() => props.signInWithGoogle()}
>
<Google className="w-50 mr-3" />
<span className="text-nowrap">Loghează-te cu Google</span>
</button>
</div>
);
};
function mapStateToProps(state) {
return {
user: state.user.data,
};
}
function mapDispatchToProps(dispatch) {
return {
signInWithGoogle: () => dispatch(loginUser()),
};
}
export default connect(mapStateToProps, mapDispatchToProps)(Login);