
前端UI組件【免費下載鏈接】react-final-form High performance subscription-based form state management for React項目地址https://gitcode.com/gh_mirrors/re/react-final-form點擊查看免費下載導讀FormRenderProps是 React Final Form 中Form/組件傳遞給渲染函數(shù)render prop或渲染組件的全部屬性的類型集合。本文圍繞倉庫中的 FormRenderProps 類型文檔 展開結合 核心實現(xiàn)源碼、類型定義 與倉庫內示例完整講解form、handleSubmit兩大核心成員、FormState各字段的惰性注入機制以及subscription如何決定你究竟能拿到哪些渲染屬性。讀完本文你將能夠正確書寫Form/的渲染函數(shù)、理解handleSubmit的返回類型規(guī)律并掌握通過訂閱裁剪渲染屬性來優(yōu)化性能的完整方案。FormRenderProps是什么FormRenderProps是Form/組件對外暴露的渲染協(xié)議。無論你使用children渲染函數(shù)、render渲染函數(shù)還是component渲染組件這三種方式收到的都是同一個FormRenderProps對象其類型簽名如下見 src/types.tsexport interface FormRenderPropsFormValues Recordstring, any extends FormStateFormValues { handleSubmit: ( event?: SubmitEvent, ) PromiseRecordstring, any | undefined | undefined; form: FormApiFormValues; }也就是說FormRenderPropsFinal Form 的FormState表單完整狀態(tài)form表單 API 實例handleSubmit提交處理函數(shù)三部分的并集。一個關鍵前提你收到的值由subscription決定FormRenderProps文檔強調的第一件事是你在渲染函數(shù)里實際能讀到的值取決于你通過subscriptionprop 訂閱了FormState中的哪些字段。subscription是一個{ [string]: boolean }對象未提供時Form/默認訂閱全部表單狀態(tài)見 FormProps 文檔 與 ReactFinalForm.tsx 中的subscription all默認值此時任何表單狀態(tài)變化都會觸發(fā)Form/及其整棵子樹重渲染。倉庫中的 subscriptions 示例 直觀演示了這一點兩個形態(tài)完全相同的表單一個不傳subscription每次輸入都重渲染整個表單與所有字段另一個只傳subscription{{ submitting: true, pristine: true }}僅當提交狀態(tài)或 pristine 變化時重渲染后者的字段因此變得相互獨立渲染計數(shù)顯著下降。這意味著FormRenderProps并不是一個固定不變的快照而是你所訂閱狀態(tài)子集的投影——合理裁剪訂閱是 React Final Form 高性能的關鍵。formFinal Form 的FormApiFormRenderProps.form的類型是 Final Form 的FormApi它是你在渲染層操作表單的命令入口典型成員包括submit()執(zhí)行一次表單提交reset(values?)將表單重置為初始值可傳入新值change(name, value)以編程方式修改某個字段的值getState()同步讀取當前表單狀態(tài)setConfig(...)動態(tài)更新配置如onSubmit、validate、initialValuesmutators命名變換器對應mutatorspropregisterField(...)注冊/注銷字段Field/內部使用源碼中的form包裝對reset的合成事件保護在 ReactFinalForm.tsx 中渲染屬性里的form并不是 Final Form 實例的裸引用而是經過一次淺包裝const renderProps: FormRenderPropsFormValues { form: { ...form, reset: (eventOrValues?: any) { if (isSyntheticEvent(eventOrValues)) { // its a React SyntheticEvent, call reset with no arguments form.reset(); } else { form.reset(eventOrValues); } }, }, handleSubmit, } as FormRenderPropsFormValues;這里通過 isSyntheticEvent.ts 判斷傳入?yún)?shù)是否為 React 合成事件如果你直接把form.reset綁定給某個按鈕的onClick例如button typebutton onClick{form.reset}Reset/button見 simple 示例React 會把合成事件作為參數(shù)傳入——此時包裝層會忽略該事件、以無參形式調用真正的form.reset()避免把事件對象誤當成重置值。測試用例 ReactFinalForm.test.js 專門驗證了這一行為先修改字段值、再點擊 Reset字段恢復為初始值John同文件后續(xù)用例還驗證了reset可以接受新的初始值對象should accept new initial values on form reset。在渲染函數(shù)中如何使用form以 simple 示例 為模板渲染函數(shù)中解構出的form通常用于重置表單Form onSubmit{onSubmit} initialValues{{ stooge: larry, employed: false }} render{({ handleSubmit, form, submitting, pristine, values }) ( form onSubmit{handleSubmit} {/* 字段省略 */} div classNamebuttons button typesubmit disabled{submitting || pristine} Submit /button button typebutton onClick{form.reset} disabled{submitting || pristine} Reset /button /div /form )} /需要強調的是form本身不受subscription裁剪它始終可用而form.getState()返回的才是完整的FormState。handleSubmit交給form的提交處理函數(shù)handleSubmit是FormRenderProps中最重要的函數(shù)成員類型簽名為(?SyntheticEventHTMLFormElement) ?Promise?Object它的設計意圖非常明確——直接作為form標簽的onSubmit使用form onSubmit{handleSubmit} ...fields go here... /form源碼實現(xiàn)三步提交流程ReactFinalForm.tsx 中的handleSubmit實現(xiàn)清晰呈現(xiàn)了它的全部行為const handleSubmit (event?: SubmitEvent) { if (event) { // sometimes not true, e.g. React Native if (typeof event.preventDefault function) { event.preventDefault(); } if (typeof event.stopPropagation function) { // prevent any outer forms from receiving the event too event.stopPropagation(); } } return form.submit(); };event.preventDefault()阻止瀏覽器默認的表單提交行為頁面刷新/跳轉這正是 React Final Form 以 JavaScript 接管提交的基礎event.stopPropagation()阻止事件冒泡避免嵌套在外部form中的表單把提交事件冒泡給外層表單return form.submit()調用 Final Form 的提交流程校驗 → 通過則調用onSubmit并把提交結果原樣返回。注意源碼中的兩處防御性判斷event可能是undefined例如在 React Native 等無 DOM 事件的環(huán)境下且preventDefault/stopPropagation可能不存在——因為 SubmitEvent 被定義為僅含這兩個可選方法的寬松接口。測試用例 ReactFinalForm.test.js 明確驗證了handleSubmit可以無參調用、也可以被傳入{}這樣的非事件對象而不會拋錯。返回值類型取決于你的onSubmit寫法handleSubmit的返回類型?Promise?Object并不是固定值而是由Form/的onSubmitprop 的寫法決定共有三種方式onSubmit寫法成功時失敗時handleSubmit的返回值同步函數(shù)返回undefined返回提交錯誤對象Object同步返回undefined或錯誤對象異步 回調返回undefined調用callback()返回undefined以錯誤對象調用callback(errors)同步返回undefined異步 Promise返回 resolve 的Promise?Object無值resolve一個提交錯誤對象返回該Promise這里有一個容易踩坑的語義異步onSubmit的錯誤不是通過 reject 拋出而是 resolve 一個錯誤對象——reject 保留給服務端或通信類異常如網(wǎng)絡中斷。測試用例 ReactFinalForm.test.js 驗證了異步場景當onSubmit是async函數(shù)時handleSubmit(event)返回一個帶.then方法的 Promise因此你可以這樣等待一次完整提交const onSubmit async (values) { await sleep(300); // 模擬網(wǎng)絡請求 window.alert(JSON.stringify(values, 0, 2)); }; // 渲染函數(shù)中 {({ handleSubmit }) ( form onSubmit{(event) { const promise handleSubmit(event); // promise 存在且可 await用于提交成功后的跳轉等后續(xù)邏輯 }} {/* ... */} /form )}此外提交錯誤對象必須與表單值的結構一致若要返回針對整個表單的通用錯誤例如Login Failed應使用 Final Form 的專用FORM_ERROR字符串鍵見 FormProps 文檔。校驗與提交的完整調用鏈結合 Form 文檔 與源碼可以梳理出handleSubmit背后的完整流程用戶點擊button typesubmit觸發(fā)form onSubmit{handleSubmit}handleSubmit阻止默認行為并調用form.submit()Final Form 依次運行字段級校驗Field.validate與整表校驗Form.validate若validateOnBlur為false則在提交時再次全量校驗存在校驗錯誤時onSubmit不會被調用校驗通過后才調用onSubmit(values, form, callback)。Form/在每次渲染時會通過useWhenValueChanges監(jiān)聽onSubmit等配置的變化并調用form.setConfig(onSubmit, onSubmit)同步到 Final Form 實例見 ReactFinalForm.tsx因此渲染函數(shù)拿到的handleSubmit始終指向最新配置下的提交邏輯。FormState渲染屬性中的全部狀態(tài)字段FormRenderProps繼承了 Final FormFormState的完整字段集。這些字段不是靜態(tài)拷貝而是在 getters.ts 中通過addLazyFormState以惰性 getterlazy getter方式掛載到渲染屬性對象上的export const addLazyFormState (dest, state) addLazyState(dest, state, [ active, dirty, dirtyFields, dirtySinceLastSubmit, dirtyFieldsSinceLastSubmit, error, errors, hasSubmitErrors, hasValidationErrors, initialValues, invalid, modified, modifiedSinceLastSubmit, pristine, submitError, submitErrors, submitFailed, submitSucceeded, submitting, touched, valid, validating, values, visited, ]);每個字段都通過Object.defineProperty定義了指向當前表單狀態(tài)的 getter見 getters.ts保證渲染時讀取到的永遠是最新的狀態(tài)值。常用字段含義如下字段含義values當前表單的全部值initialValues初始值與當前值比較用于計算pristine/dirtypristine/dirty表單是否與初始值一致 / 已被修改submitting是否正在提交用于禁用提交按鈕submitFailed/submitSucceeded最近一次提交是否失敗 / 成功submitError/submitErrors整表提交錯誤FORM_ERROR/ 按字段的提交錯誤errors/hasValidationErrors全部校驗錯誤 / 是否存在校驗錯誤invalid/valid是否有校驗錯誤注意invalid包含hasValidationErrorsvalidating是否有異步校驗正在進行active當前聚焦字段名或undefinedtouched/visited各字段是否被觸碰 / 訪問過dirtySinceLastSubmit/dirtyFieldsSinceLastSubmit自上次提交后表單/字段是否被改動modified/modifiedSinceLastSubmit字段是否被修改過與 dirty 的細微差別見 Final Form 文檔在渲染函數(shù)中最常用的組合是({ handleSubmit, form, submitting, pristine, values })見 simple 示例用submitting/pristine控制按鈕禁用用values實時預覽表單數(shù)據(jù)。三種渲染方式與FormRenderProps的傳遞FormRenderProps無論通過哪種方式都能完整到達渲染方Form 文檔Prop類型說明Form component/React.ComponentTypeFormRenderProps以React.createElement()渲染組件組件會真實存在于 React 節(jié)點樹中可在 DevTools 中檢視Form render/(props: FormRenderProps) React.Node渲染函數(shù)社區(qū)推薦Form children/((props: FormRenderProps) React.Node) \| React.Node渲染函數(shù)或普通子節(jié)點三個 prop 的優(yōu)先級與合并規(guī)則由 renderComponent.ts 實現(xiàn)component優(yōu)先其次是render最后才是函數(shù)型children三者均缺失時拋出Must specify either a render prop, a render function as children, or a component prop錯誤。若同時指定render與childrenrender會被調用而children會作為額外 prop 注入。此外你在Form/上傳入的任意非 API 自定義 prop例如someArbitraryOtherProp{42}也會一并合并進FormRenderProps對象見 FormProps 文檔 與 renderComponent.ts 中的合并邏輯。一個完整的實戰(zhàn)模板綜合以上所有內容一個生產可用的Form/渲染函數(shù)模板如下參考 simple 示例 與 subscriptions 示例import React from react; import { Form, Field } from react-final-form; const sleep (ms) new Promise((resolve) setTimeout(resolve, ms)); const required (value) (value ? undefined : Required); // 異步 onSubmit返回 Promise成功 resolve 無值失敗 resolve 錯誤對象 const onSubmit async (values) { await sleep(300); window.alert(JSON.stringify(values, 0, 2)); }; const MyForm () ( Form onSubmit{onSubmit} initialValues{{ firstName: }} // 性能優(yōu)化只訂閱渲染函數(shù)真正用到的狀態(tài) subscription{{ submitting: true, pristine: true, values: true }} render{({ handleSubmit, form, submitting, pristine, values }) ( form onSubmit{handleSubmit} Field namefirstName validate{required} {({ input, meta }) ( div input {...input} placeholderFirst Name / {meta.touched meta.error span{meta.error}/span} /div )} /Field div classNamebuttons button typesubmit disabled{submitting || pristine} Submit /button button typebutton onClick{form.reset} // 自動屏蔽 React 合成事件 disabled{submitting || pristine} Reset /button /div pre{JSON.stringify(values, 0, 2)}/pre /form )} / );與FormSpy的配合不重渲染表單也能讀取狀態(tài)由于subscription裁剪后FormRenderProps中的values等字段可能不再更新若仍需要在表單外實時展示狀態(tài)應改用FormSpy/單獨訂閱。這正是 subscriptions 示例 的做法當渲染函數(shù)未訂閱values時改用FormSpy subscription{{ values: true }}包裹一個只渲染pre的展示組件。FormSpy收到的FormSpyRenderProps與FormRenderProps結構類似繼承FormStateform見 src/types.ts但不含handleSubmit——它只用于觀察狀態(tài)不參與提交。小結FormRenderProps是 React Final Form 渲染層的完整協(xié)議由三部分組成formFormApi操作表單的命令入口reset經包裝可安全綁定到事件處理器handleSubmit直接交給form的提交函數(shù)自動preventDefault/stopPropagation并返回form.submit()的結果其返回類型跟隨onSubmit的三種寫法同步 / 回調 / Promise而變化FormState全字段通過惰性 getter 掛載保證讀到最新狀態(tài)實際可讀字段由subscription決定合理訂閱是控制重渲染范圍、優(yōu)化性能的核心手段。想進一步深入可以繼續(xù)閱讀倉庫中的 Form 組件文檔、FormProps 類型文檔 以及訂閱式狀態(tài)管理的實戰(zhàn)示例 examples/subscriptions/index.js并在 src/ReactFinalForm.tsx 與 src/ReactFinalForm.test.js 中查看實現(xiàn)與測試細節(jié)。贊分享前端UI組件【免費下載鏈接】react-final-form High performance subscription-based form state management for React項目地址https://gitcode.com/gh_mirrors/re/react-final-form點擊查看免費下載相關推薦React Final Form API 完全指南從 Form/、Field/ 到 useField() 的訂閱式表單狀態(tài)管理React Final Form API 完全指南從 Form/ 、 Field/ 到 useField 的訂閱式表單狀態(tài)管理 導讀 本文以倉庫中的 do前端UI組件react-final-form 的 FormProps 完全指南從渲染模式到訂閱式狀態(tài)管理的配置詳解react final form 的 FormProps 完全指南從渲染模式到訂閱式狀態(tài)管理的配置詳解 導讀 FormProps 是 react final前端UI組件React Final Form 的 Field/ 組件完全指南注冊、訂閱與渲染字段的官方 API 詳解React Final Form 的 Field/ 組件完全指南注冊、訂閱與渲染字段的官方 API 詳解 導讀 本文以 React Final Form 官前端UI組件上一篇極速語音交互FunASR WebSocket服務的實時通信技術解密下一篇Bilibili-Evolved暗色模式終極指南提升可訪問性與視覺體驗創(chuàng)作聲明:本文部分內容由AI輔助生成(AIGC),僅供參考