Login State

介绍

LoginState 是一个和登录相关的状态管理中心,专门用于管理登录的状态和操作。它提供了自动登录、手动登录、登出等功能,并支持登录状态的实时监听和错误处理。
该 Hook 具备以下特色:
自动登录管理 - 支持传入配置后自动初始化和登录
手动登录控制 - 提供手动登录和登出方法
状态实时同步 - 实时更新登录状态和错误信息
重复登录防护 - 防止重复登录和配置变更时的智能处理

useLoginState 参数

字段
类型
描述
config
LoginConfig
登录配置
config 参数是登录配置,用于初始化登录状态。在组件中直接使用则会自动登录。
LoginConfig 定义如下:
interface LoginConfig {
userID: string; // 用户 ID
SDKAppID: number; // 腾讯云应用 ID
userSig: string; // 用户签名
onSuccess?: () => void; // 登录成功回调
onError?: (error: Error) => void; // 登录失败回调
}

useLoginState 返回值

字段
类型
描述
status
LoginStatus
当前登录状态
error
Error | null
登录过程中的错误信息
currentConfig
LoginConfig | null
当前使用的登录配置
login
(config: LoginConfig) => Promise<void>
手动登录方法
logout
() => Promise<void>
登出方法

详细字段说明

status

类型: LoginStatus
描述: 当前登录状态,用于跟踪登录过程的各个阶段。
枚举定义:
enum LoginStatus {
IDLE, // 空闲状态,未开始登录
LOADING, // 登录中
SUCCESS, // 登录成功
ERROR, // 登录失败
}

error

类型: Error | null
描述: 登录过程中发生的错误信息。当登录成功或未发生错误时为 null

currentConfig

类型: LoginConfig | null
描述: 当前使用的登录配置信息。用于比较配置变更和防止重复登录。

login

类型: (config: LoginConfig) => Promise<void>
描述: 手动登录方法。可以传入完整的登录配置进行登录。
参数: config - 登录配置对象
返回值: Promise<void> - 登录完成的 Promise

logout

类型: () => Promise<void>
描述: 登出方法。清除登录状态并调用 SDK 的登出接口。
返回值: Promise<void> - 登出完成的 Promise

使用示例

方式一:自动登录(推荐)

这是最简单的使用方式,传入登录配置后会自动初始化并登录:
import React from 'react';
import { useLoginState, LoginStatus } from './states/LoginState/LoginState';

function App() {
const { status, error, logout } = useLoginState({
userID: 'your-userID-here',
SDKAppID: 0, // your-SDKAppID-here, this is number type!
userSig: 'your-userSig-here',
onSuccess: () => console.log('🎉 登录成功!'),
onError: (error) => console.error('❌ 登录失败:', error),
});

// 根据登录状态渲染不同内容
if (status === LoginStatus.LOADING) {
return <div className="loading">登录中...</div>;
}

if (status === LoginStatus.ERROR) {
return (
<div className="error">
<p>登录失败: {error?.message}</p>
<button onClick={() => window.location.reload()}>重试</button>
</div>
);
}

if (status !== LoginStatus.SUCCESS) {
return <div className="waiting">等待登录...</div>;
}

return (
<div className="app">
<header className="app-header">
<h1>聊天应用</h1>
<button onClick={logout} className="logout-btn">
登出
</button>
</header>
<UIKitProvider>
</UIKitProvider>
</div>
);
}

export default App;

方式二:手动控制登录

这种方式提供更多的控制权,可以在需要时手动触发登录:
import React, { useState } from 'react';
import { useLoginState, LoginStatus } from './states/LoginState/LoginState';

function ManualLoginApp() {
const { login, logout, status, error, client } = useLoginState(); // 不传配置
const [loginForm, setLoginForm] = useState({
userID: '',
SDKAppID: 0,
userSig: '',
});

const handleLogin = async () => {
try {
await login({
...loginForm,
onSuccess: () => {
console.log('登录成功!');
// 可以在这里进行登录后的操作
},
onError: (error) => {
console.error('登录失败:', error);
// 可以在这里处理登录错误
},
});
} catch (error) {
console.error('登录异常:', error);
}
};

const handleLogout = async () => {
try {
await logout();
console.log('登出成功!');
} catch (error) {
console.error('登出失败:', error);
}
};

const isLoggedIn = status === LoginStatus.SUCCESS;

return (
<div className="manual-login-app">
{!isLoggedIn ? (
<div className="login-form">
<h2>登录</h2>
<div className="form-group">
<label>用户 ID:</label>
<input
type="text"
value={loginForm.userID}
onChange={(e) => setLoginForm(prev => ({ ...prev, userID: e.target.value }))}
placeholder="请输入用户 ID"
/>
</div>
<div className="form-group">
<label>SDK App ID:</label>
<input
type="number"
value={loginForm.SDKAppID}
onChange={(e) => setLoginForm(prev => ({ ...prev, SDKAppID: Number(e.target.value) }))}
placeholder="请输入 SDK App ID"
/>
</div>
<div className="form-group">
<label>用户签名:</label>
<textarea
value={loginForm.userSig}
onChange={(e) => setLoginForm(prev => ({ ...prev, userSig: e.target.value }))}
placeholder="请输入用户签名"
/>
</div>
<button
onClick={handleLogin}
disabled={status === LoginStatus.LOADING}
className="login-btn"
>
{status === LoginStatus.LOADING ? '登录中...' : '登录'}
</button>
{error && (
<div className="error-message">
错误: {error.message}
</div>
)}
</div>
) : (
<div className="app-content">
<div className="app-header">
<h1>聊天应用</h1>
<button onClick={handleLogout} className="logout-btn">
登出
</button>
</div>
<ChatApp client={client} />
</div>
)}
</div>
);
}

export default ManualLoginApp;
效果图如下图所示:


样式参考

以下是配套的 SCSS 样式,可以根据需要进行调整:
// 基础样式
.loading {
display: flex;
justify-content: center;
align-items: center;
height: 100vh;
font-size: 18px;
color: #666;
}

.error {
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
height: 100vh;
p {
color: #ff4444;
margin-bottom: 16px;
}
button {
padding: 8px 16px;
background: #007bff;
color: white;
border: none;
border-radius: 4px;
cursor: pointer;
&:hover {
background: #0056b3;
}
}
}

// 应用样式
.app {
height: 100vh;
display: flex;
flex-direction: column;
.app-header {
display: flex;
justify-content: space-between;
align-items: center;
padding: 16px 24px;
background: #f8f9fa;
border-bottom: 1px solid #e9ecef;
h1 {
margin: 0;
color: #333;
}
.logout-btn {
padding: 8px 16px;
background: #dc3545;
color: white;
border: none;
border-radius: 4px;
cursor: pointer;
&:hover {
background: #c82333;
}
}
}
}

// 手动登录表单样式
.manual-login-app {
height: 100vh;
display: flex;
justify-content: center;
align-items: center;
.login-form {
width: 400px;
padding: 32px;
border: 1px solid #e9ecef;
border-radius: 8px;
background: white;
box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1);
h2 {
text-align: center;
margin-bottom: 24px;
color: #333;
}
.form-group {
margin-bottom: 16px;
label {
display: block;
margin-bottom: 4px;
color: #555;
font-weight: 500;
}
input, textarea {
width: 100%;
padding: 8px 12px;
border: 1px solid #ddd;
border-radius: 4px;
font-size: 14px;
&:focus {
outline: none;
border-color: #007bff;
}
}
textarea {
height: 80px;
resize: vertical;
}
}
.login-btn {
width: 100%;
padding: 12px;
background: #007bff;
color: white;
border: none;
border-radius: 4px;
font-size: 16px;
cursor: pointer;
&:hover:not(:disabled) {
background: #0056b3;
}
&:disabled {
background: #ccc;
cursor: not-allowed;
}
}
.error-message {
margin-top: 12px;
padding: 8px;
background: #f8d7da;
color: #721c24;
border-radius: 4px;
font-size: 14px;
}
}
}

注意事项

1. 参数验证: 确保传入的 userIDSDKAppIDuserSig 都是有效的。
2. 错误处理: 始终处理登录可能出现的错误情况。
3. 状态监听: 合理使用登录状态来控制 UI 显示。
4. 资源清理: 在组件卸载时及时调用 logout 方法。
5. 安全性: 不要在客户端硬编码敏感信息,userSig 应该从服务器获取。