一个属性是不确定的-在React中从类组件切换到函数钩子组件 [英] A property is undefined - switching from class components to function hooks components in React

查看:29
本文介绍了一个属性是不确定的-在React中从类组件切换到函数钩子组件的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

当我尝试将Bootcamp项目代码从类组件切换到有状态功能组件时遇到此错误:

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]);

这发生在登录"组件中,该组件负责显示通过Firebase服务通过Google进行连接的选项,并重定向到useEffect试图执行的首页.

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.

下面的代码中注释了componentDidUpdate方法的代码,该方法正是在该组件是一个类时执行的.

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);

此外,下面是包含整个应用程序的github存储库的链接.

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!

使用该答案,我得到以下错误:

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

无论我是否导入useRef,都会重现该错误.当前组件看起来像这样:

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);

推荐答案

最后,我设法通过添加一个布尔值来解决此问题,该值将检查是否需要重定向并将其存储在状态中-难看但有些有效

In the end, I managed to solve this by adding a boolean value that would check if I need to redirect and stored that in the state - ugly but somewhat efficient.

import React, { useEffect, useState } 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/user/userAction";

const Login = (props) => {

    const [redirect, changeRedirect] = useState(false);
    const { user, history, signInWithGoogle } = props;
    useEffect(() => {
        if(redirect){
            history.push("/");
        }
    }, [user, history]);

    const handleClick = () => {
        changeRedirect(true);
        signInWithGoogle();
    }

    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={() => handleClick()}
            >
                <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);

这篇关于一个属性是不确定的-在React中从类组件切换到函数钩子组件的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆