将基于 class 的组件转换为挂钩 (gapi API)
Converting a class based component to hooks (gapi API)
我有这个基于 class 的组件,它使用 gapi (Google Auth) API 呈现一个按钮并且它有效:
import React from 'react';
class GoogleAuth extends React.Component {
state = { isSignedIn: null };
componentDidMount() {
window.gapi.load('client:auth2', () => {
window.gapi.client
.init({
clientId: process.env.REACT_APP_CLIENT_ID,
scope: 'email',
})
.then(() => {
this.auth = window.gapi.auth2.getAuthInstance();
this.handleAuthChange();
this.auth.isSignedIn.listen(this.handleAuthChange);
});
});
}
handleAuthChange = () => {
this.setState({ isSignedIn: this.auth.isSignedIn.get() });
};
handleSignIn = () => {
this.auth.signIn();
};
handleSignOut = () => {
this.auth.signOut();
};
renderAuthButton() {
if (this.state.isSignedIn === null) {
return null;
} else if (this.state.isSignedIn) {
return <button onClick={this.handleSignOut}>Sign Out</button>;
} else {
return <button onClick={this.handleSignIn}>Sign in with Google</button>;
}
}
render() {
return <div>{this.renderAuthButton()}</div>;
}
}
export default GoogleAuth;
我很难尝试将其转换为使用挂钩。主要问题是 this.auth
... 这就是 class 引用 window.gapi.auth2.getAuthInstance()
的方式
我尝试了很多不同的方法,包括将身份验证保持在以下状态:
export default function GoogleAuth() {
const [isSignedIn, setIsSignedIn] = useState(null);
const [auth, setAuth] = useState(null);
useEffect(() => {
window.gapi.load('client:auth2', () => {
window.gapi.client
.init({
clientId: process.env.REACT_APP_CLIENT_ID,
scope: 'email',
})
.then(() => {
setAuth(window.gapi.auth2.getAuthInstance());
setIsSignedIn(auth.isSignedIn.get());
auth.isSignedIn.listen(() => setIsSignedIn(auth.isSignedIn.get()));
});
});
}, [auth]);
几个问题 - 您在设置状态后立即引用 auth
- auth
将不会设置,直到它以新状态重新呈现。
我正在玩类似的代码,我不得不在初始设置中使用 window.gapi
来正确访问返回的 auth 实例。
我想如果用户快速点击它可能会抛出一个错误,他们可以在设置 auth
之前捕捉到它,但我发现符号 in/out 函数能够处理这个问题。
我还发现在隐身模式下测试最容易,因为 api 的 cookie 和缓存似乎会创建一个不可预测的本地测试环境。
仅仅 8 个月后,请像下面那样尝试使用带有身份验证的 useRef。对我有用。
const GoogleAuth = () => {
const [isSignedIn, setSignedIn] = useState(null)
const auth = useRef(null);
useEffect(() => {
window.gapi.load('client:auth2', () => {
window.gapi.client.init({
clientId:
'jcu.apps.googleusercontent.com',
scope: 'email'
}).then(() => {
auth.current = window.gapi.auth2.getAuthInstance();
setSignedIn(auth.current.isSignedIn.get());
auth.current.isSignedIn.listen(onAuthChange)
});
});
}, [isSignedIn]);
const onAuthChange = () => {
setSignedIn(auth.current.isSignedIn.get())
}
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>);
}
}
只需在 auth.current = ... 之后的 useEffect 行
setSignedIn(auth.current.isSignedIn.get());
是事实上的函数 onAuthChange
所以这样称呼它:
.then(() => {
auth.current = window.gapi.auth2.getAuthInstance();
onAuthChange();
auth.current.isSignedIn.listen(onAuthChange);
});
我有这个基于 class 的组件,它使用 gapi (Google Auth) API 呈现一个按钮并且它有效:
import React from 'react';
class GoogleAuth extends React.Component {
state = { isSignedIn: null };
componentDidMount() {
window.gapi.load('client:auth2', () => {
window.gapi.client
.init({
clientId: process.env.REACT_APP_CLIENT_ID,
scope: 'email',
})
.then(() => {
this.auth = window.gapi.auth2.getAuthInstance();
this.handleAuthChange();
this.auth.isSignedIn.listen(this.handleAuthChange);
});
});
}
handleAuthChange = () => {
this.setState({ isSignedIn: this.auth.isSignedIn.get() });
};
handleSignIn = () => {
this.auth.signIn();
};
handleSignOut = () => {
this.auth.signOut();
};
renderAuthButton() {
if (this.state.isSignedIn === null) {
return null;
} else if (this.state.isSignedIn) {
return <button onClick={this.handleSignOut}>Sign Out</button>;
} else {
return <button onClick={this.handleSignIn}>Sign in with Google</button>;
}
}
render() {
return <div>{this.renderAuthButton()}</div>;
}
}
export default GoogleAuth;
我很难尝试将其转换为使用挂钩。主要问题是 this.auth
... 这就是 class 引用 window.gapi.auth2.getAuthInstance()
我尝试了很多不同的方法,包括将身份验证保持在以下状态:
export default function GoogleAuth() {
const [isSignedIn, setIsSignedIn] = useState(null);
const [auth, setAuth] = useState(null);
useEffect(() => {
window.gapi.load('client:auth2', () => {
window.gapi.client
.init({
clientId: process.env.REACT_APP_CLIENT_ID,
scope: 'email',
})
.then(() => {
setAuth(window.gapi.auth2.getAuthInstance());
setIsSignedIn(auth.isSignedIn.get());
auth.isSignedIn.listen(() => setIsSignedIn(auth.isSignedIn.get()));
});
});
}, [auth]);
几个问题 - 您在设置状态后立即引用 auth
- auth
将不会设置,直到它以新状态重新呈现。
我正在玩类似的代码,我不得不在初始设置中使用 window.gapi
来正确访问返回的 auth 实例。
我想如果用户快速点击它可能会抛出一个错误,他们可以在设置 auth
之前捕捉到它,但我发现符号 in/out 函数能够处理这个问题。
我还发现在隐身模式下测试最容易,因为 api 的 cookie 和缓存似乎会创建一个不可预测的本地测试环境。
仅仅 8 个月后,请像下面那样尝试使用带有身份验证的 useRef。对我有用。
const GoogleAuth = () => {
const [isSignedIn, setSignedIn] = useState(null)
const auth = useRef(null);
useEffect(() => {
window.gapi.load('client:auth2', () => {
window.gapi.client.init({
clientId:
'jcu.apps.googleusercontent.com',
scope: 'email'
}).then(() => {
auth.current = window.gapi.auth2.getAuthInstance();
setSignedIn(auth.current.isSignedIn.get());
auth.current.isSignedIn.listen(onAuthChange)
});
});
}, [isSignedIn]);
const onAuthChange = () => {
setSignedIn(auth.current.isSignedIn.get())
}
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>);
}
}
只需在 auth.current = ... 之后的 useEffect 行
setSignedIn(auth.current.isSignedIn.get());
是事实上的函数 onAuthChange
所以这样称呼它:
.then(() => {
auth.current = window.gapi.auth2.getAuthInstance();
onAuthChange();
auth.current.isSignedIn.listen(onAuthChange);
});