当前位置: 首页 > article >正文

使用react进行用户管理系统

        今天通了一遍使用react进行用户管理系统的文档,以及跟随步骤实现了一遍,我大概梳理一下实现思路。

        首先我们构建基本用户管理应用,需要数据库存储个人资料,我们先去supabase注册然后创建自己的数据库然后设置密码,然后去sql editor找到模板,user management starter创建一个空表profiles,这时候我们有了我们自己的数据库以及数据表,当然我们在创建表的时候也创建了相关的后端逻辑,也就是说supabase是一个自带后端的数据库,平台帮你一键搞定数据库、认证、权限、安全等基础设施,我们只需要调用平台接口,关注业务逻辑和前端开发。然后我们需要把官网创建的云端数据库拉取到本地,首先呢我们需要npm install -g supabase安装 Supabase CLI工具,它可以初始化本地 Supabase 项目(supabase init)关联本地和云端项目(supabase link)拉取云端数据库结构(supabase db pull)本地启动 Supabase 开发环境(supabase start)等等。

        然后下载完工具后,我们初始化本地supabase项目,也就是supabase init,然后我们需要登录supabase cli,让cil工具识别我们我们才可以supabase link执行这个把项目拉取到本地,这时候密码输入就算本地supabase和线上数据库连接了,然后supabase db pull拉取到本地supabase项目,我们就算是把云端的数据库表结构拿了过来。表结构包括表,函数,以及后端策略。

        然后我们创建react模板的vite项目,新建.env.local文件引入数据库的url和anon key然后新建supabase.js我们引入supabase-js库然后加入代码

        

import { createClient } from '@supabase/supabase-js'const supabaseUrl = import.meta.env.VITE_SUPABASE_URL
const supabaseAnonKey = import.meta.env.VITE_SUPABASE_ANON_KEYexport const supabase = createClient(supabaseUrl, supabaseAnonKey)

        我们就相当于项目和数据库完全的连接了并且可以直接使用supabase-js里面的方法api以及后端逻辑。

        那么剩下的步骤就是开发也就是写代码了。

        这里我就都不写出来了我只写登入以及信息页面的代码。

        

		import { useState } from 'react'import { supabase } from './supabaseClient'export default function Auth() {const [loading, setLoading] = useState(false)const [email, setEmail] = useState('')const handleLogin = async (event) => {event.preventDefault()setLoading(true)const { error } = await supabase.auth.signInWithOtp({ email })if (error) {alert(error.error_description || error.message)} else {alert('Check your email for the login link!')}setLoading(false)}return (<div className="row flex flex-center"><div className="col-6 form-widget"><h1 className="header">Supabase + React</h1><p className="description">Sign in via magic link with your email below</p><form className="form-widget" onSubmit={handleLogin}><div><inputclassName="inputField"type="email"placeholder="Your email"value={email}required={true}onChange={(e) => setEmail(e.target.value)}/></div><div><button className={'button block'} disabled={loading}>{loading ? <span>Loading</span> : <span>Send magic link</span>}</button></div></form></div></div>)}

        这是登录页面,下面是个人信息页面

       

import { useState, useEffect } from 'react'
import { supabase } from './supabaseClient'
export default function Account({ session }) {
const [loading, setLoading] = useState(true)
const [username, setUsername] = useState(null)
const [website, setWebsite] = useState(null)
const [avatar_url, setAvatarUrl] = useState(null)
useEffect(() => {
let ignore = false
async function getProfile() {
setLoading(true)
const { user } = session
const { data, error } = await supabase
.from('profiles')
.select(username, website, avatar_url)
.eq('id', user.id)
.single()
if (!ignore) {
if (error) {
console.warn(error)
} else if (data) {
setUsername(data.username)
setWebsite(data.website)
setAvatarUrl(data.avatar_url)
}
}
setLoading(false)
}
getProfile()
return () => {
ignore = true
}
}, [session])
async function updateProfile(event, avatarUrl) {
event.preventDefault()
setLoading(true)
const { user } = session
const updates = {
id: user.id,
username,
website,
avatar_url: avatarUrl,
updated_at: new Date(),
}
const { error } = await supabase.from('profiles').upsert(updates)
if (error) {
alert(error.message)
} else {
setAvatarUrl(avatarUrl)
}
setLoading(false)
}
return (
<form onSubmit={updateProfile} className="form-widget">
<div>
<label htmlFor="email">Email</label>
<input id="email" type="text" value={session.user.email} disabled />
</div>
<div>
<label htmlFor="username">Name</label>
<input
id="username"
type="text"
required
value={username || ''}
onChange={(e) => setUsername(e.target.value)}
/>
</div>
<div>
<label htmlFor="website">Website</label>
<input
id="website"
type="url"
value={website || ''}
onChange={(e) => setWebsite(e.target.value)}
/>
</div>
<div>
<button className="button block primary" type="submit" disabled={loading}>
{loading ? 'Loading ...' : 'Update'}
</button>
</div>
<div>
<button className="button block" type="button" onClick={() => supabase.auth.signOut()}>
Sign Out
</button>
</div>
</form>
)
}

以及app页面

        

import './App.css'
import { useState, useEffect } from 'react'
import { supabase } from './supabaseClient'
import Auth from './Auth'
import Account from './Account'
function App() {
const [session, setSession] = useState(null)
useEffect(() => {
supabase.auth.getSession().then(({ data: { session } }) => {
setSession(session)
})
supabase.auth.onAuthStateChange((_event, session) => {
setSession(session)
})
}, [])
return (
<div className="container" style={{ padding: '50px 0 100px 0' }}>
{!session ? <Auth /> : <Account key={session.user.id} session={session} />}
</div>
)
}
export default App

        现在我们总结一下思路,登录页面auth.jsx,关键是 await supabase.auth.signInWithOtp({ email })这个supabase自带的otp登录api,实现用户通过邮箱验收验证码的方式登录,无需密码,然后onChange={(e) => setEmail(e.target.value)}监听输入框内的内容,把内容存入状态,提交就可以了。

        登录成功后session会返回,我们在app根组件中监听用supabase.auth.onAutnStateChange 来监听获取session,通过session是否返回也就是是否登录来判断渲染登录页还是账户页面

        然后再账户页面,核心就是

const { data, error } = await supabase.from('profiles').select(username, website, avatar_url).eq('id', user.id).single()

        使用useEffect在账户页面加载从profiles表中读取当前用户的username,website,avataer.url然后通过表单输入框 onchange监听实时更新username和website的值,点击更新按钮触发updataProfile函数调用await supabase.from('profiles').upsert(updates)更新数据库。

        ok大概这就是核心思路,扩展的上传头像框可以去对应的文档练习,我觉得关键的思路这些已经齐全了,大家可以评论指点我一下,谢谢大家。

http://www.lryc.cn/news/2395038.html

相关文章:

  • SpringBoot的java应用中,慢sql会导致CPU暴增吗
  • Ubuntu下编译mininim游戏全攻略
  • uniapp uni-id Error: Invalid password secret
  • 用 Appuploader,让 iOS 上架流程真正“可交接、可记录、可复用”:我们是这样实现的
  • 第十二节:第三部分:集合框架:List系列集合:特点、方法、遍历方式、ArrayList集合的底层原理
  • 【办公类-18-07】20250527屈光检查PDF文件拆分成多个pdf(两页一份,用幼儿班级姓名命名文件)
  • AI Agent的“搜索大脑“进化史:从Google API到智能搜索生态的技术变革
  • Arduino学习-跑马灯
  • python创建args命令行分析
  • 2. 手写数字预测 gui版
  • js数据类型有哪些?它们有什么区别?
  • 大模型应用开发第五讲:成熟度模型:从ChatGPT(L2)到未来自主Agent(L4)
  • 特别篇-产品经理(三)
  • IP地址扫描 网络状态监测 企业网络管理 免安装,企业级 IP 监控防未授权接入
  • 【unity游戏开发——编辑器扩展】AssetDatabase公共类在编辑器环境中管理和操作项目中的资源
  • BLE协议全景图:从0开始理解低功耗蓝牙
  • 【机器学习基础】机器学习入门核心算法:GBDT(Gradient Boosting Decision Tree)
  • 基于开源AI大模型AI智能名片S2B2C商城小程序源码的销售环节数字化实现路径研究
  • Spring Cache核心原理与快速入门指南
  • Redisson学习专栏(四):实战应用(分布式会话管理,延迟队列)
  • java程序从服务器端到Lambda函数的迁移与优化
  • 使用yocto搭建qemuarm64环境
  • Vue 3前沿生态整合:WebAssembly与TypeScript深度实践
  • Linux系统下安装配置 Nginx
  • Kotlin 中集合遍历有哪几种方式?
  • 图像卷积OpenCV C/C++ 核心操作
  • LiveGBS作为下级平台GB28181国标级联2016|2022对接海康大华宇视华为政务公安内网等GB28181国标平台查看级联状态及会话
  • leetcode17.电话号码的字母组合:字符串映射与回溯的巧妙联动
  • Gartner《2025 年软件工程规划指南》报告学习心得
  • 数据库 | 使用timescaledb和大模型进行数据分析