為什么說(shuō)form元素是React的未來(lái)
思考一個(gè)問(wèn)題
如果有一個(gè)HTML
標(biāo)簽,React
圍繞他專門出了2個(gè)hook
,那這個(gè)標(biāo)簽對(duì)React
未來(lái)的發(fā)展一定非常重要,這沒(méi)毛病吧?
這個(gè)標(biāo)簽就是 —— form
。
React
圍繞form
新出了如下2個(gè)hook
:
useOptimistic
useFormStatus
Next.js的發(fā)展歷程
說(shuō)到React
未來(lái)的發(fā)展,必須從Next.js
聊起。畢竟,React
團(tuán)隊(duì)成員不是加入Next
團(tuán)隊(duì),就是在加入的路上。
web
開發(fā)中涉及到前后端交互的部分主要包括:
- 根據(jù)后端數(shù)據(jù)渲染前端頁(yè)面
- 根據(jù)前端用戶輸入保存數(shù)據(jù)到后端
Next.js
的發(fā)展主要圍繞以上兩點(diǎn)展開。
根據(jù)后端數(shù)據(jù)渲染前端頁(yè)面
前期,Next.js
的主打特性是SSR
、SSG
。也就是把根據(jù)后端數(shù)據(jù)渲染前端頁(yè)面的過(guò)程從前端挪到后端。
這個(gè)時(shí)期的Next.js
路由被稱為Pages Router
。
時(shí)間來(lái)到Next.js v13
,以RSC
(React Server Component)為核心的App Router
取代Pages Router
成為默認(rèn)配置。
很多朋友不熟悉RSC
,認(rèn)為他是實(shí)驗(yàn)特性。實(shí)際上,RSC
借由Next.js
已經(jīng)落地了。
一句話理解RSC
—— 客戶端組件(在瀏覽器渲染的React
組件)可以根據(jù)依賴分為兩部分:
- 依賴數(shù)據(jù)源(比如數(shù)據(jù)庫(kù)、文件系統(tǒng))的組件,可以作為
RSC
(服務(wù)端組件) - 依賴狀態(tài)(比如
state
、props
、context
)的組件,可以作為客戶端組件
從根據(jù)后端數(shù)據(jù)渲染前端頁(yè)面角度看:
SSR
、SSG
是頁(yè)面級(jí)別的(服務(wù)端渲染呈現(xiàn)的是整個(gè)頁(yè)面)RSC
是組件級(jí)別的(服務(wù)端組件請(qǐng)求數(shù)據(jù)源)
根據(jù)前端用戶輸入保存數(shù)據(jù)到后端
聊完了根據(jù)后端數(shù)據(jù)渲染前端頁(yè)面,那么,圍繞根據(jù)前端用戶輸入保存數(shù)據(jù)到后端,Next.js
能做哪些優(yōu)化?
這就要提到Next.js
的實(shí)驗(yàn)特性 —— Server Action
。
Server Action
根據(jù)前端用戶輸入保存數(shù)據(jù)到后端的常見(jiàn)場(chǎng)景是表單提交,通常我們會(huì)在form
的obSubmit
事件中做后續(xù)處理:
function Form() { function submit() { // ...處理formData的邏輯 // ...發(fā)送請(qǐng)求的邏輯 } return ( <form onSubmit={submit}> <input type="text"/> <input type="text"/> </form> ) }
以上代碼有什么可改進(jìn)的地方呢?
從用戶體驗(yàn)的角度看,如果前端禁用了JS
,那么React
不能運(yùn)行,上述交互失效。如果在禁用JS
的情況下也能提交表單就好了。
從開發(fā)體驗(yàn)的角度看,submit
方法會(huì)發(fā)起請(qǐng)求,后端再根據(jù)請(qǐng)求攜帶的formData
操作數(shù)據(jù)庫(kù),比較繁瑣。如果在submit
方法內(nèi)能直接操作數(shù)據(jù)庫(kù)就好了。
Server Action
特性就是為了實(shí)現(xiàn)以上2個(gè)目標(biāo)。
首先來(lái)看第一個(gè)目標(biāo)。
目標(biāo)1
HTML
原生的form
元素有個(gè)action
屬性,可以接收一個(gè)url
。當(dāng)提交表單(比如點(diǎn)擊type
為submit
的按鈕)后formData
會(huì)提交給該url
。
<form action="/action_page.php" method="get"> <label for="fname">First name:</label> <input type="text" id="fname" name="fname"><br><br> <label for="lname">Last name:</label> <input type="text" id="lname" name="lname"><br><br> <input type="submit" value="Submit"> </form>
由于提交表單的行為是HTML
原生支持的,所以在禁用JS
的情況下也能執(zhí)行。
這就是禁用JS
也能提交表單的理論基礎(chǔ)。
目標(biāo)2
React
擴(kuò)展了form
的action
屬性,讓他除了支持url
,還能支持回調(diào)函數(shù),比如:
function App() { function submit(data) { // ... } return ( <form action={submit}> <! -- 省略 --> </form> );
如果這個(gè)回調(diào)函數(shù)內(nèi)是前端執(zhí)行的邏輯,則被稱為client action
,比如下面這樣:
async function submit(data) { await const res = saveData(data); // ... }
如果這個(gè)函數(shù)內(nèi)是后端執(zhí)行的邏輯,則被稱為server action
,比如下面這樣:
"use server" async function submit(data) { const userID = cookies().get("userID")?.value; await db.users.update(userID, data); // ... }
"use server"
標(biāo)記代表這是個(gè)server action
。
如果是server action
,那么發(fā)起的請(qǐng)求類型是multipart/form-data
(即表單提交):
響應(yīng)類型則是RSC協(xié)議
:
也就是說(shuō),有了server action
,開發(fā)者可以直接在form
的action
屬性(或者button
的formAction
屬性等其他幾種屬性)內(nèi)書寫后端邏輯,并且在瀏覽器禁用JS
的情況下這些邏輯也能執(zhí)行。
2個(gè)新hook
為了更好的服務(wù)server action
,React
團(tuán)隊(duì)新出了2個(gè)hook
用于提高form
場(chǎng)景下的用戶體驗(yàn):
useOptimistic
useFormStatus
當(dāng)前,這2個(gè)hook
的介紹只能在Next.js文檔(而不是React
文檔)中看到。
useOptimistic
主要用來(lái)優(yōu)化提交數(shù)據(jù)的用戶體驗(yàn)。
比如,在點(diǎn)贊的場(chǎng)景,通常邏輯是:
- 點(diǎn)擊點(diǎn)贊按鈕
- 發(fā)起點(diǎn)贊請(qǐng)求
- 點(diǎn)贊成功,前端顯示點(diǎn)贊效果
但為了用戶體驗(yàn)的流暢,前端通常會(huì)把邏輯做成:
- 點(diǎn)擊點(diǎn)贊按鈕
- 前端顯示點(diǎn)贊效果(同時(shí)發(fā)起點(diǎn)贊請(qǐng)求)
- 根據(jù)請(qǐng)求結(jié)果,如果點(diǎn)贊成功則不做處理,如果點(diǎn)贊失敗則重置按鈕
useOptimistic
的本質(zhì)就是在狀態(tài)層面實(shí)現(xiàn)上述效果。
useFormStatus
則用于在表單提交過(guò)程中顯示pending
狀態(tài):
function ButtonDisabledWhilePending({action, children}) { const {pending} = useFormStatus(); return ( <button disabled={pending} formAction={action}> {children} </button> ); }
有同學(xué)可能會(huì)疑惑:useFormStatus
沒(méi)有傳參,他怎么知道對(duì)應(yīng)哪個(gè)form
?
實(shí)際上,為了實(shí)現(xiàn)useFormStatus
,React
在源碼內(nèi)為所有HostComponent
(即原生HTML
元素對(duì)應(yīng)組件,比如<div/>
)定制了一個(gè)context
。
當(dāng)某個(gè)form
觸發(fā)表單提交時(shí),context
的值會(huì)被更新為這個(gè)form
的數(shù)據(jù)。useFormStatus
本身僅僅是useContext(上述context)
。
總結(jié)
可以發(fā)現(xiàn),不管是useFormStatus
、useOptimistic
還是最近1~2年新出的hook
(比如useId
、useMutableSource
),我們開發(fā)者都很少會(huì)用到。
因?yàn)檫@些hook
都是為上層框架(主要是Next.js
)提供的。
React
早已完成他作為前端框架的使命。在他生命的后半程,他將作為上層框架的操作系統(tǒng)而存在。
server action
是Next.js
的未來(lái),Next.js
是React
的未來(lái)。所以,React
的未來(lái)會(huì)圍繞form
元素持續(xù)布局。
以上就是form元素是React的未來(lái)的詳細(xì)內(nèi)容,更多關(guān)于form元素是React的未來(lái)的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
ahooks整體架構(gòu)及React工具庫(kù)源碼解讀
這篇文章主要為大家介紹了ahooks整體架構(gòu)及React工具庫(kù)的源碼解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-07-07React項(xiàng)目動(dòng)態(tài)修改主題顏色的方案
這篇文章主要介紹了React項(xiàng)目動(dòng)態(tài)修改主題顏色的方案,文中通過(guò)代碼示例講解的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作有一定的幫助,需要的朋友可以參考下2025-01-01使用react-virtualized實(shí)現(xiàn)圖片動(dòng)態(tài)高度長(zhǎng)列表的問(wèn)題
一般我們?cè)趯憆eact項(xiàng)目中,同時(shí)渲染很多dom節(jié)點(diǎn),會(huì)造成頁(yè)面卡頓, 空白的情況。為了解決這個(gè)問(wèn)題,今天小編給大家分享一篇教程關(guān)于react-virtualized實(shí)現(xiàn)圖片動(dòng)態(tài)高度長(zhǎng)列表的問(wèn)題,感興趣的朋友跟隨小編一起看看吧2021-05-05React中引入less、less-loader問(wèn)題
這篇文章主要介紹了React中引入less、less-loader問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2024-01-01React實(shí)現(xiàn)createElement 和 cloneElement的區(qū)別
本文詳細(xì)介紹了React中React.createElement和React.cloneElement兩種方法的定義、用法、區(qū)別及適用場(chǎng)景,具有一定的參考價(jià)值,感興趣的可以了解一下2024-09-09ahooks封裝cookie?localStorage?sessionStorage方法
這篇文章主要為大家介紹了ahooks封裝cookie?localStorage?sessionStorage的方法示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-07-07如何使用 React Router v6 在 React 中
面包屑在網(wǎng)頁(yè)開發(fā)中的角色不可忽視,它們?yōu)橛脩籼峁┝艘环N跟蹤其在網(wǎng)頁(yè)中當(dāng)前位置的方法,并有助于網(wǎng)頁(yè)導(dǎo)航,本文介紹了如何使用react-router v6和bootstrap在react中實(shí)現(xiàn)面包屑,感興趣的朋友一起看看吧2024-09-09