reactjs - 属性未定义 - 在 React 中从类组件切换到函数挂钩组件
问题描述
我在尝试将我的训练营项目代码从类组件切换到有状态功能组件时遇到了这个错误:
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]);
这发生在 Login 组件中,该组件负责显示通过 Google 连接的选项 - 使用 firebase 服务,并重定向到主页,这是 useEffect 试图做的。
下面在代码中注释的是 componentDidUpdate 方法的代码,它在组件是一个类时执行此操作。
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);
此外,下面是包含整个应用程序的 github 存储库的链接。
https://github.com/vradu007/radu-shop
如果你能告诉我我做错了什么,请告诉我——我没有在训练营学习过钩子,但我在工作中使用它们,我一直在尝试通过在线查找来掌握它。谢谢!
编辑:使用该答案,我收到以下错误:
./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
无论我是否导入 useRef,都会重现该错误。当前组件如下所示:
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);
解决方案
由于您无法使用 useEffect 达到 prevProps ,因此另一种方法是使用 useRef 保存该值然后进行比较。
import React, { useEffect , useRef} from "react";
function usePrevious(value) {
const ref = useRef();
useEffect(() => {
ref.current = value;
});
return ref.current;
}
并为您的 useEffect 进行此更改
const previous = usePrevious({props.user, props.history});
useEffect((prevProps) => {
if (props.user !== previous.user) {
props.history.push("/");
}
}, [props.user, props.history]);
我的答案基于该答案:如何在 React Hooks useEffect 上比较 oldValues 和 newValues?
- usePrevious:https ://usehooks.com/usePrevious/
- 使用参考: https ://reactjs.org/docs/hooks-reference.html#useref
推荐阅读
- jenkins - 从工作区文件中读取的反应选择参数
- javascript - 我可以在网页内容中获取图像 url 并显示到 chrome 扩展中吗?
- c# - 如何使用 Ninject 提供额外的参数?
- java - 如何在 Spring MVC 中为简单表继承域创建控制器?
- reactjs - React redux 无法验证用户身份
- wordpress - 301永久移动了怎么解决?
- kotlin - onApplyWindowInsets(WindowInsets insets) 没有被调用
- python - 将应用程序 urls.py 链接到项目的 urls.py 时出现“未找到:/”错误
- javascript - 在理解标记模板方面需要帮助
- java - 使用 kotlin 反射将对象成员属性映射到 hashmap 时出现问题