将基于 class 的组件重构为挂钩 (gapi API)

Refactoring a class based component to hooks (gapi API)

我正在尝试将基于 class 的组件重构为使用挂钩的功能组件。尝试获取我的登录状态时,我卡在了 gapi 中 useState 的正确使用上。

只是想知道,我想得到什么:

1) 获取对"auth"对象初始化后的引用

2) 弄清楚我目前是否已登录

3) 在屏幕上打印我的身份验证状态

这里已经提出了类似的问题: 但不幸的是,我没有将答案应用到我的案例中。

这是 class 组件:

import React from "react";

class GoogleAuth extends React.Component {
    componentDidMount() {
        window.gapi.load("client: auth2", () => {
            window.gapi.client
                .init({
                    clientId: "myVerySecretAPI",
                    scope: "email"
                })
                .then(() => {
                    this.auth = window.gapi.auth2.getAuthInstance(); //this gets me acces to the auth object
                    this.setState({ isSignedIn: this.auth.isSignedIn.get() });
                });
        });
    }

    renderAuthButton() {
        if (this.state.isSignedIn === null) {
            return <div>I dont know if we are signed in</div>;
        } else if (this.state.isSignedIn) {
            return <div>I am signed in!</div>;
        } else {
            return <div>I am not signed in</div>;
        }
    }

    render() {
        return <div>{this.renderAuthButton()}</div>;
    }
}

export default GoogleAuth;

这是我重构的代码:

import React, { useEffect, useState } from "react";

const GoogleAuth = () => {
    const [ auth, setAuth ] = useState(null);

    useEffect(
        () => {
            window.gapi.load("client:auth2", () => {
                window.gapi.client
                    .init({
                        clientId: "834243588921-gob95b7q7n3eids3fm8du8oharkv5od0.apps.googleusercontent.com",
                        scope: "email"
                    })
                    .then(() => {
                        setAuth(window.gapi.auth2.getAuthInstance());
                        auth({ isSignedIn: setAuth.isSignedIn.get() }); // this is the line where I get an error (please see below)
                    });
            });
        },
        [ auth ]
    );

    const renderAuthButton = (isSignedIn) => {
        if (isSignedIn === null) {
            return <div>I dont know if we are signed in</div>;
        } else if (isSignedIn) {
            return <div>I am signed in!</div>;
        } else {
            return <div>I am not signed in</div>;
        }
    };

    return <div>{renderAuthButton()}</div>;
};

export default GoogleAuth;

我在 chrome 中收到错误消息:

未捕获类型错误:无法读取 GoogleAuth.js:16

处未定义的 属性 'get'

我知道,我缺少一些了解挂钩使用的小东西。 欢迎任何帮助!

所以你基本上是在节省一些东西。第一个是您从 window.gapi.auth2.getAuthInstance() 获得的 actual 身份验证实例,第二个是已验证状态 isSignedIn。在您的代码中,您 setAuth 使用实例,但随后尝试调用已保存的实例并向其传递一些新对象,其中 isSignedIn 作为键,状态 setter 作为值。这行不通。

您可以先获取实例,然后使用该实例从中获取身份验证状态以保存到您的状态中。您还应该使用一个空的依赖项数组,这样当 GoogleAuth 被挂载时效果是 运行 一次。

此外,您的 renderAuthButton 函数被定义为采用 isSignedIn 参数,但您没有在 return 中向其传递任何内容。由于这是一个功能组件,尽管您可以简单地省略参数并在范围内使用状态值。

const GoogleAuth = () => {
  const [isSignedIn, setIsSignedIn ] = useState(null);

  useEffect(
    () => {
      window.gapi.load("client:auth2", () => {
        window.gapi.client
          .init({
            clientId: "834243588921-gob95b7q7n3eids3fm8du8oharkv5od0.apps.googleusercontent.com",
             scope: "email"
          })
          .then(() => {
            const authInstance = window.gapi.auth2.getAuthInstance();
            setIsSignedIn(authInstance.isSignedIn.get());
          });
      });
    },
    []
  );

  const renderAuthButton = () => {
    if (isSignedIn === null) {
      return <div>I don't know if we are signed in</div>;
    } else if (isSignedIn) {
      return <div>I am signed in!</div>;
    } else {
      return <div>I am not signed in</div>;
    }
  };

  return <div>{renderAuthButton()}</div>;
};