[譯]React中的用戶認(rèn)證(登錄態(tài)管理)

本文主要展示在當(dāng)下React應(yīng)用開發(fā)中,怎么使用Context和Hooks來管理用戶的認(rèn)證(也就是登錄態(tài))瓦呼。

先說結(jié)論

下面是本文最終要實(shí)現(xiàn)的的簡化版划咐,方便大佬們直接看最后的效果:

importReactfrom'react'import{useUser}from'./context/auth'importAuthenticatedAppfrom'./authenticated-app'importUnauthenticatedAppfrom'./unauthenticated-app'functionApp(){constuser = useUser()returnuser ?:}export App復(fù)制代碼

嗯熟史,最終的代碼大概就長這樣。大多數(shù)需要進(jìn)行用戶認(rèn)證管理的應(yīng)用肋殴,都可以使用類似上面的邏輯來管理用戶登錄狀態(tài)囤锉。當(dāng)用戶訪問我們應(yīng)用中的某個(gè)需要登錄后才能訪問的頁面時(shí),我們可以將用戶重定向到登陸頁护锤,大多數(shù)情況下也是這樣做的官地,除此之外,我們還可以不進(jìn)行跳轉(zhuǎn)烙懦,直接在該頁面上展示未登錄用戶看到的界面驱入。為了提高用戶體驗(yàn),我們也可以這樣:

importReactfrom'react'import{useUser}from'./context/auth'constAuthenticatedApp = React.lazy(()=>import('./authenticated-app'))constUnauthenticatedApp = React.lazy(()=>import('./unauthenticated-app'))functionApp(){constuser = useUser()returnuser ?:}export App復(fù)制代碼

親,代碼懶加載就實(shí)現(xiàn)了:未登錄用戶訪問我們頁面亏较,只會(huì)加載渲染未登錄界面的代碼莺褒;已登錄用戶訪問同一個(gè)頁面,同樣只會(huì)加載渲染已登錄界面的代碼雪情。

具體在AuthenticatedApp和UnauthenticatedApp里渲染什么界面遵岩,完全是開發(fā)者來決定⊙餐ǎ或許他們會(huì)渲染一些router尘执,甚至?xí)?fù)用一些公共組件。無論具體渲染什么宴凉,我們都不用關(guān)心用戶的登錄態(tài)了誊锭,因?yàn)樵阡秩具@兩個(gè)組件之一的時(shí)候,已經(jīng)明確知道了用戶的登錄狀態(tài)弥锄。

怎么一步步實(shí)現(xiàn)上面的邏輯

如果你想看看最終整個(gè)APP的實(shí)現(xiàn)丧靡,可以到這個(gè)github查看。

OK籽暇,我們接下來看看怎么一步步來實(shí)現(xiàn)上面的邏輯温治。首先,我們看下我們應(yīng)用的入口代碼:

importReactfrom'react'importReactDOMfrom'react-dom'importAppfrom'./app'importAppProvidersfrom'./context'ReactDOM.render(,document.getElementById('root'),)復(fù)制代碼

下面是AppProviders組件的代碼:

importReactfrom'react'import{AuthProvider}from'./auth-context'import{UserProvider}from'./user-context'functionAppProviders({children}){return({children})}exportdefaultAppProviders復(fù)制代碼

OK戒悠,我們有兩個(gè)Provider: 一個(gè)是維護(hù)應(yīng)用的認(rèn)證狀態(tài)罐盔;另一個(gè)是維護(hù)當(dāng)前登錄用戶的數(shù)據(jù)。按照字面意思救崔,AppProvider負(fù)責(zé)初始化整個(gè)APP的數(shù)據(jù)(如果在localStorage中存在用戶認(rèn)證后的token,那么我們可以直接從token中獲取一些用戶數(shù)據(jù))捏顺。另一方面六孵,UserProvider負(fù)責(zé)將我們對用戶數(shù)據(jù)的一些修改(比如email地址、履歷等)保持和服務(wù)器端的同步幅骄。

完整的auth-context.js包含一些和本文主題無關(guān)的邏輯劫窒,因此下面我們來看下簡化版的auth-context.js:

importReactfrom'react'import{FullPageSpinner}from'../components/lib'constAuthContext = React.createContext()functionAuthProvider(props){// 如果我們還不確定當(dāng)前用戶是否登錄,比如還在請求后端接口查詢登錄狀態(tài)拆座,// 那么我們就渲染一個(gè)全局的加載中主巍,而不是加載真正的頁面組件if(weAreStillWaitingToGetTheUserData) {return? }? const login = () => {} // make a login request? const register = () => {} // register the user? const logout = () => {} // clear the token in localStorage and the user data? // 注意:這里我并沒有使用 `React.useMemo` 來優(yōu)化 provider 的 `value`。? // 因?yàn)檫@是我們應(yīng)用里最頂級(jí)的組件挪凑,很少會(huì)在這個(gè)頂級(jí)組件上觸發(fā) 重新render? return (? ? ? )}const useAuth = () => React.useContext(AuthContext)export {AuthProvider, useAuth}// user-context.js 文件里的 `UserProvider` 大概長這樣:// const UserProvider = props => (//? // )// and the useUser hook is basically this:// const useUser = () => React.useContext(UserContext)復(fù)制代碼

簡化我們應(yīng)用里的認(rèn)證管理的關(guān)鍵點(diǎn)是:

負(fù)責(zé)維護(hù)用戶登錄態(tài)的組件孕索,在獲取到當(dāng)前用戶的登錄狀態(tài)之前,不會(huì)渲染頁面的主體內(nèi)容躏碳,可以渲染一個(gè)加載中的全局loading搞旭。只有當(dāng)從服務(wù)器端獲取到用戶的登錄狀態(tài)之后,才去渲染頁面的主體:已登錄就渲染登錄后的組件;未登錄渲染未登錄的肄渗。

結(jié)論

在實(shí)際開發(fā)中镇眷,很多APP面臨的場景都是不同的。如果你采用了服務(wù)端渲染技術(shù)(SSR)翎嫡,那么你很可能不需要一個(gè)加載中的loading欠动,因?yàn)槟阍诜?wù)端已經(jīng)明確知道了,當(dāng)前用戶是否已登錄惑申。即使在這個(gè)場景下具伍,同樣可以將用戶的登錄狀態(tài)提出到全局的Provider來管理,這樣會(huì)增強(qiáng)我們代碼的可維護(hù)性硝桩。

PS

有些同學(xué)問到了相同的問題:如果我們的應(yīng)用沿猜,已登錄用戶和未登錄用戶看到的很多界面都相同(比如twitter),而不是像gmail那樣碗脊,已登錄用戶和未登錄用戶看到的完全不同啼肩,我們應(yīng)該怎么來維護(hù)用戶登錄狀態(tài)呢?

如果是這種情況,那么代碼里很多組件衙伶,都會(huì)用到useUser這個(gè)hook祈坠,為了能在一個(gè)公共組件中,根據(jù)是否登錄而執(zhí)行不同邏輯矢劲。因?yàn)槲覀兊墓步M件可能值關(guān)心用戶是否登錄赦拘,你甚至可以再封裝出一個(gè)useIsAuthenticatedhook,返回一個(gè)boolean值芬沉,表示當(dāng)前用戶是否已登錄躺同。多虧了Context和Hooks,要實(shí)現(xiàn)這樣的邏輯非常的簡單丸逸。

我自己是一個(gè)從事了6年的Java全棧工程師蹋艺,最近整理了一套適合2019年學(xué)習(xí)的Java\大數(shù)據(jù)資料,從基礎(chǔ)的Java黄刚、大數(shù)據(jù)面向?qū)ο蟮竭M(jìn)階的框架知識(shí)都有整理哦捎谨,可以來我的主頁免費(fèi)領(lǐng)取哦。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末憔维,一起剝皮案震驚了整個(gè)濱河市涛救,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌业扒,老刑警劉巖检吆,帶你破解...
    沈念sama閱讀 206,214評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異程储,居然都是意外死亡咧栗,警方通過查閱死者的電腦和手機(jī)逆甜,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,307評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來致板,“玉大人交煞,你說我怎么就攤上這事≌寤颍” “怎么了素征?”我有些...
    開封第一講書人閱讀 152,543評(píng)論 0 341
  • 文/不壞的土叔 我叫張陵,是天一觀的道長萝挤。 經(jīng)常有香客問我御毅,道長,這世上最難降的妖魔是什么怜珍? 我笑而不...
    開封第一講書人閱讀 55,221評(píng)論 1 279
  • 正文 為了忘掉前任端蛆,我火速辦了婚禮,結(jié)果婚禮上酥泛,老公的妹妹穿的比我還像新娘今豆。我一直安慰自己,他們只是感情好柔袁,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,224評(píng)論 5 371
  • 文/花漫 我一把揭開白布呆躲。 她就那樣靜靜地躺著,像睡著了一般捶索。 火紅的嫁衣襯著肌膚如雪插掂。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,007評(píng)論 1 284
  • 那天腥例,我揣著相機(jī)與錄音辅甥,去河邊找鬼。 笑死燎竖,一個(gè)胖子當(dāng)著我的面吹牛肆氓,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播底瓣,決...
    沈念sama閱讀 38,313評(píng)論 3 399
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼蕉陋!你這毒婦竟也來了捐凭?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 36,956評(píng)論 0 259
  • 序言:老撾萬榮一對情侶失蹤凳鬓,失蹤者是張志新(化名)和其女友劉穎茁肠,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體缩举,經(jīng)...
    沈念sama閱讀 43,441評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡垦梆,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,925評(píng)論 2 323
  • 正文 我和宋清朗相戀三年匹颤,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片托猩。...
    茶點(diǎn)故事閱讀 38,018評(píng)論 1 333
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡印蓖,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出京腥,到底是詐尸還是另有隱情赦肃,我是刑警寧澤,帶...
    沈念sama閱讀 33,685評(píng)論 4 322
  • 正文 年R本政府宣布公浪,位于F島的核電站他宛,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏欠气。R本人自食惡果不足惜厅各,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,234評(píng)論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望预柒。 院中可真熱鬧队塘,春花似錦、人聲如沸卫旱。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,240評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽顾翼。三九已至投放,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間适贸,已是汗流浹背灸芳。 一陣腳步聲響...
    開封第一講書人閱讀 31,464評(píng)論 1 261
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留拜姿,地道東北人烙样。 一個(gè)月前我還...
    沈念sama閱讀 45,467評(píng)論 2 352
  • 正文 我出身青樓,卻偏偏與公主長得像蕊肥,于是被迫代替她去往敵國和親谒获。 傳聞我的和親對象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,762評(píng)論 2 345

推薦閱讀更多精彩內(nèi)容

  • react+redux+webpack+babel+npm+shell+git這方面的內(nèi)容我會(huì)隨時(shí)更新壁却,更新內(nèi)容放...
    liangklfang閱讀 648評(píng)論 0 1
  • 3. JSX JSX是對JavaScript語言的一個(gè)擴(kuò)展語法批狱, 用于生產(chǎn)React“元素”,建議在描述UI的時(shí)候...
    pixels閱讀 2,806評(píng)論 0 24
  • 以下內(nèi)容是我在學(xué)習(xí)和研究React時(shí)展东,對React的特性赔硫、重點(diǎn)和注意事項(xiàng)的提取、精練和總結(jié)盐肃,可以做為React特性...
    科研者閱讀 8,219評(píng)論 2 21
  • 我總是不愿意主動(dòng)出擊爪膊,自己的事情自己不上心权悟,沒有人會(huì)幫你,只有靠自己才是真理推盛,現(xiàn)在放假閑在家里峦阁,想找工作沒有行動(dòng),...
    仲孫書琴閱讀 247評(píng)論 0 0
  • Day—10打卡 五月精讀主題營 精讀書目:《說話的魅力》 /劉墉 “有人說小槐,愈是笑話多的民族拇派,愈顯示文化的深厚,...
    ZH寰宇閱讀 237評(píng)論 0 6