feat(#3): Formik adapter — formdraft/formik subpath#10
Merged
Conversation
Closes #3. Mirrors the formdraft/rhf pattern for users on Formik. const formik = useFormik({ initialValues: { name: '', bio: '' }, onSubmit: async (v) => { await api.submit(v); discard(); // clears storage + broadcasts + resets formik }, }); const { status, lastSavedAt, discard } = useFormDraftFormik(formik, { key: 'profile-form', schema: zodAdapter(Schema), sync: api.saveProfile, }); ## Vetting 5 rounds of code review + adversarial audit dispatched in parallel each round. Real bugs caught and fixed before merge: R1: discard wiped storage but left the visible formik input intact, so the next keystroke re-persisted the "discarded" text back to storage. → discard now also calls form.resetForm(). R1: restore called form.setValues(value) which defaulted shouldValidate=true, painting validation errors against text the user never typed. → setValues(draft.values, false). R2: identity churn — Formik recreates handlers on every render with inline onReset/initialErrors, making `discard` re-create each render and break consumer useEffect deps. → formRef pattern reads latest form.resetForm via ref. R3: restore caused a sync round-trip on every page load (setValues leaves formik.dirty=true → persist effect fires → patches restored data back into draft → enqueues sync of unchanged values). → ignoreNextFormChangeRef set by restore-effect, consumed + cleared by the next value-watcher run. R3: delete-back-to-initial silently dropped (formik.dirty flips false → patch effect skipped → stored draft survives → next mount restores "deleted" text). Canonical autosave failure mode. → sticky userTouchedRef (set on observed dirty=true, never auto-reset); discard() resets it so post-discard resetForm doesn't re-patch. R4: latch hasRestoredRef when restore skipped due to form.dirty so we don't re-evaluate it on every subsequent patch. ## Tests 10 unit tests: - persist on input change - restore from storage on mount - restore does NOT trigger validation (F1 regression) - discard clears storage AND visible input (F3 regression) - submit pattern: discard in onSubmit clears storage - delete-back-to-initial persists deletion (F2 regression) - restore does NOT trigger redundant sync (F1/ignoreNext regression) - type-clear-late-restore: cleared input stays cleared (D5 latent race) - user-types-before-restore race (deferred storage harness) - underlying useFormDraft cleanup verified via discard Wired in: - package.json adds formdraft/formik to exports + formik as optional peer - tsup adds formik/index entry → dist/formik/{index.mjs,index.js,index.d.ts} - README adds Formik integration section with submit-pattern example Total 115 unit tests pass. Bundle 4.09 KB brotli (Formik adapter goes into its own chunk; main entry size unchanged).
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #3.
Summary
formdraft/formikexportsuseFormDraftFormik(formik, options)formdraft/rhfpattern: thin adapter overuseFormDraft, returns the persistence-layer surface (status, lastSavedAt, error, save, discard, etc.) without the value/set/patch API (Formik owns those)formikadded as optional peer dependencyVetting
5 rounds of code review + adversarial audit dispatched in parallel each round. Real bugs caught:
Test plan
npm test— 115 unit tests pass (10 Formik adapter + 105 existing)npx size-limit— 4.09 KB brotli (Formik adapter in its own chunk, main entry unchanged)