如何在Kotlin/JS中集成Google GSI?遇属性未定义错误求解决
Kotlin/JS React Google一键登录:错误修复与资源参考
先解决当前的Cannot read properties of undefined (reading 'accounts')错误
这个问题的核心是你用了async defer加载Google GSI脚本,导致React组件的useEffect执行时,window.google还没被初始化。这里有几种靠谱的解决方式:
方式1:轮询检查Google对象是否加载完成
在useEffect里写一个递归检查的函数,直到google对象存在再执行初始化:
val SignIn = FC<Props> { useEffect { fun initGoogleSignIn() { val google = window.asDynamic().google if (google != undefined) { google.accounts.id.initialize( js("{ client_id: '你的客户端ID', callback: (response) => { /* 处理登录回调逻辑 */ } }") ) } else { setTimeout({ initGoogleSignIn() }, 100) } } initGoogleSignIn() } }
方式2:监听脚本加载完成事件
在index.html里给脚本添加onload回调,触发自定义事件后再在React组件里执行初始化:
- 修改
index.html:
<script> function onGoogleGSILoaded() { window.dispatchEvent(new Event('googleGSILoaded')); } </script> <script src="https://accounts.google.com/gsi/client" async defer onload="onGoogleGSILoaded()"></script>
- 在Kotlin组件里监听事件:
val SignIn = FC<Props> { useEffect { val handleLoad = { val google = window.asDynamic().google google.accounts.id.initialize(/* 你的配置参数 */) } // 检查是否已经加载完成 if (window.asDynamic().google?.accounts != undefined) { handleLoad() } else { window.addEventListener("googleGSILoaded", handleLoad) } // 组件卸载时清理事件监听 return@useEffect { window.removeEventListener("googleGSILoaded", handleLoad) } } }
Kotlin封装库与实现参考
目前没有官方专门针对Google GSI的Kotlin/JS封装库,但可以自己封装类型安全的交互层,避免全用dynamic:
// 定义类型安全的外部接口 external interface GoogleSignInConfig { val client_id: String val callback: (GoogleSignInResponse) -> Unit } external interface GoogleSignInResponse { val credential: String val select_by: String } external interface GoogleAccountsId { fun initialize(config: GoogleSignInConfig) fun renderButton(element: Element, config: dynamic) } external interface GoogleAccounts { val id: GoogleAccountsId } external interface Google { val accounts: GoogleAccounts } // 全局获取Google对象 val google: Google? get() = window.asDynamic().google?.unsafeCast<Google?>()
之后就可以用类型安全的方式调用API,不用再依赖dynamic。
参考方向:
- 遵循Google Identity Services官方的Web端实现规范,明确需要调用的API参数和回调逻辑
- 参考Kotlin/JS官方的JS互操作文档,学习如何正确定义外部接口和处理JS对象
内容的提问来源于stack exchange,提问作者nightlytrails
相关产品推荐
相关产品推荐

