├── .babelrc.js ├── .codesandbox └── ci.json ├── .eslintrc ├── .flowconfig ├── .github ├── CODE_OF_CONDUCT.md ├── CONTRIBUTING.md ├── FUNDING.yml ├── ISSUE_TEMPLATE.md ├── PULL_REQUEST_TEMPLATE.md └── workflows │ ├── ci.yml │ └── lock.yml ├── .gitignore ├── .prettierignore ├── .prettierrc ├── .travis.yml ├── LICENSE ├── README.md ├── banner.png ├── docs ├── HolyJS2018.gif ├── ReactAlicante2018.gif ├── api.md ├── api │ ├── Field.md │ ├── Form.md │ ├── FormSpy.md │ ├── useField.md │ ├── useForm.md │ └── useFormState.md ├── examples.md ├── examples │ ├── chakra.md │ ├── field-level-validation.md │ ├── record-level-validation.md │ ├── simple.md │ ├── submission-errors.md │ ├── subscriptions.md │ └── wizard.md ├── faq.md ├── getting-started.md ├── logo.pdf ├── logo.svg ├── migration │ ├── formik.md │ └── redux-form.md ├── philosophy.md ├── sencha.svg └── types │ ├── FieldProps.md │ ├── FieldRenderProps.md │ ├── FormProps.md │ ├── FormRenderProps.md │ ├── FormSpyProps.md │ └── FormSpyRenderProps.md ├── eslint.config.js ├── examples ├── async-field-level-validation │ ├── Spinner.js │ ├── Styles.js │ ├── index.js │ ├── package.json │ └── readme.md ├── async-redux-submission │ ├── Styles.js │ ├── asyncSubmissionMiddleware.js │ ├── index.js │ ├── package.json │ ├── readme.md │ ├── registrationDuck.js │ └── store.js ├── async-typeahead-redux │ ├── GithubUserTypeahead.jsx │ ├── Styles.js │ ├── actions.js │ ├── index.js │ ├── package.json │ ├── readme.md │ ├── store.js │ └── useKeyword.js ├── auto-save-field-blur │ ├── AutoSave.js │ ├── Styles.js │ ├── index.js │ ├── package.json │ └── readme.md ├── auto-save-selective-debounce │ ├── AutoSave.js │ ├── Styles.js │ ├── index.js │ ├── package.json │ └── readme.md ├── auto-save-with-debounce │ ├── AutoSave.js │ ├── Styles.js │ ├── index.js │ ├── package.json │ └── readme.md ├── calculated-fields │ ├── Styles.js │ ├── index.js │ ├── package.json │ └── readme.md ├── chakra │ ├── index.js │ ├── package.json │ ├── readme.md │ └── validate.js ├── conditional-fields │ ├── Styles.js │ ├── index.js │ ├── package.json │ ├── pickupTimes.js │ └── readme.md ├── credit-card │ ├── Card.js │ ├── Styles.js │ ├── cardUtils.js │ ├── index.js │ ├── package.json │ ├── readme.md │ └── sandbox.config.json ├── custom-validation-engine │ ├── OnBlurValidation.js │ ├── Styles.js │ ├── index.js │ ├── package.json │ └── readme.md ├── debounced-record-level-validation │ ├── ErrorWithDelay.js │ ├── README.md │ ├── Styles.js │ ├── index.js │ └── package.json ├── declarative-form-rules │ ├── Styles.js │ ├── index.js │ ├── package.json │ └── readme.md ├── downshift-typeahead │ ├── DownshiftInput.js │ ├── Styles.js │ ├── fruit.js │ ├── index.js │ ├── package.json │ └── readme.md ├── external-submit │ ├── Styles.js │ ├── index.js │ ├── package.json │ └── readme.md ├── field-arrays │ ├── Styles.js │ ├── index.js │ ├── package-lock.json │ ├── package.json │ └── readme.md ├── field-level-validation │ ├── Styles.js │ ├── index.js │ ├── package.json │ └── readme.md ├── field-warnings │ ├── Styles.js │ ├── index.js │ ├── package.json │ ├── readme.md │ └── warning-engine.js ├── fields-component │ ├── Styles.js │ ├── index.js │ ├── package.json │ └── readme.md ├── focus-first-error │ ├── Styles.js │ ├── index.js │ ├── package.json │ ├── readme.md │ └── validate.js ├── format-on-blur │ ├── Styles.js │ ├── index.js │ ├── package.json │ └── readme.md ├── format-string-by-pattern │ ├── Styles.js │ ├── index.js │ ├── package.json │ └── readme.md ├── hybrid-sync-async-record-level-validation │ ├── Spinner.js │ ├── Styles.js │ ├── index.js │ ├── package.json │ └── readme.md ├── independent-error-component-render-props │ ├── Styles.js │ ├── index.js │ ├── package.json │ └── readme.md ├── independent-error-component-with-hooks │ ├── Styles.js │ ├── index.js │ ├── package.json │ └── readme.md ├── listening-for-external-changes │ ├── BooleanDecay.js │ ├── ExternalModificationDetector.js │ ├── Styles.js │ ├── index.js │ ├── package.json │ └── readme.md ├── loading-initializing-values │ ├── Styles.js │ ├── index.js │ ├── package.json │ └── readme.md ├── loading-saving-reinitializing │ ├── LoadSaveReinitializeForm.js │ ├── Styles.js │ ├── index.js │ ├── package.json │ └── readme.md ├── material-ui │ ├── .prettierrc │ ├── index.js │ ├── package.json │ └── readme.md ├── parse-format │ ├── Styles.js │ ├── index.js │ ├── package.json │ └── readme.md ├── prefixed-fields │ ├── Styles.js │ ├── index.js │ ├── package.json │ └── readme.md ├── readme.md ├── record-level-validation │ ├── Styles.js │ ├── index.js │ ├── package.json │ └── readme.md ├── redux │ ├── FormStateFromRedux.js │ ├── FormStateToRedux.js │ ├── Styles.js │ ├── finalFormDuck.js │ ├── index.js │ ├── package.json │ ├── readme.md │ └── store.js ├── reusable-field-groups │ ├── Styles.js │ ├── index.js │ ├── package.json │ └── readme.md ├── simple │ ├── Styles.js │ ├── index.js │ ├── package.json │ └── readme.md ├── strongly-typed-values-typescript │ ├── Styles.tsx │ ├── components │ │ ├── CheckboxInput.tsx │ │ ├── MultiCheckboxInput.tsx │ │ ├── MultiSelectInput.tsx │ │ ├── NumberInput.tsx │ │ ├── RadioInput.tsx │ │ ├── SelectInput.tsx │ │ ├── TextAreaInput.tsx │ │ └── TextInput.tsx │ ├── index.tsx │ └── readme.md ├── styling-with-smooth-ui │ ├── index.js │ ├── package.json │ └── readme.md ├── submission-errors │ ├── Styles.js │ ├── index.js │ ├── package.json │ └── readme.md ├── subscriptions │ ├── RenderCount.js │ ├── Styles.js │ ├── index.js │ ├── package.json │ └── readme.md ├── third-party-components │ ├── Styles.js │ ├── index.js │ ├── package.json │ ├── readme.md │ └── states.js └── wizard │ ├── Styles.js │ ├── Wizard.js │ ├── index.js │ ├── package.json │ └── readme.md ├── form-nerd-logo.png ├── logo.png ├── package-scripts.js ├── package.json ├── rollup.config.js ├── src ├── Field.test.js ├── Field.tsx ├── FormSpy.test.js ├── FormSpy.tsx ├── ReactFinalForm.test.js ├── ReactFinalForm.tsx ├── context.ts ├── getValue.test.js ├── getValue.ts ├── getters.ts ├── index.ts ├── isReactNative.ts ├── isSyntheticEvent.ts ├── renderComponent.test.js ├── renderComponent.ts ├── shallowEqual.test.js ├── shallowEqual.ts ├── testUtils.ts ├── types.ts ├── useConstant.ts ├── useConstantCallback.test.js ├── useConstantCallback.ts ├── useField.test.js ├── useField.ts ├── useForm.test.js ├── useForm.ts ├── useFormState.test.js ├── useFormState.ts ├── useLatest.ts └── useWhenValueChanges.ts ├── tsconfig.build.json ├── tsconfig.json ├── tslint.json ├── typescript ├── Field.test.tsx ├── FormSpy.test.tsx ├── ReactFinalForm.test.tsx ├── index.d.ts ├── tsconfig.json ├── useField.test.tsx └── useFormState.test.tsx └── yarn.lock /.babelrc.js: -------------------------------------------------------------------------------- 1 | const { NODE_ENV } = process.env; 2 | const test = NODE_ENV === "test"; 3 | const loose = true; 4 | 5 | module.exports = { 6 | presets: [ 7 | [ 8 | "@babel/preset-env", 9 | { 10 | loose, 11 | ...(test ? { targets: { node: "8" } } : {}), 12 | }, 13 | ], 14 | "@babel/preset-react", 15 | "@babel/preset-typescript", 16 | ], 17 | plugins: [ 18 | "@babel/plugin-syntax-dynamic-import", 19 | "@babel/plugin-syntax-import-meta", 20 | test && "@babel/plugin-transform-react-jsx-source", 21 | ].filter(Boolean), 22 | }; 23 | -------------------------------------------------------------------------------- /.codesandbox/ci.json: -------------------------------------------------------------------------------- 1 | { 2 | "sandboxes": [ 3 | "/examples/simple", 4 | "/examples/record-level-validation", 5 | "/examples/field-level-validation", 6 | "/examples/submission-errors", 7 | "/examples/subscriptions" 8 | ], 9 | "node": "18", 10 | "installCommand": "setup" 11 | } 12 | -------------------------------------------------------------------------------- /.eslintrc: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "react-app", 3 | "plugins": ["react-hooks"], 4 | "rules": { 5 | "jsx-a11y/href-no-hash": 0, 6 | "react-hooks/rules-of-hooks": "error", 7 | "react-hooks/exhaustive-deps": "warn", 8 | "import/no-anonymous-default-export": 0 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /.flowconfig: -------------------------------------------------------------------------------- 1 | [ignore] 2 | dist 3 | 4 | [include] 5 | 6 | [libs] 7 | 8 | [options] 9 | -------------------------------------------------------------------------------- /.github/CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing 2 | 3 | Thanks for your interest in contributing to 🏁 React Final Form! Please take a 4 | moment to review this document **before submitting a pull request**. 5 | 6 | We are open to, and grateful for, any contributions made by the community. 7 | 8 | ## Reporting issues and asking questions 9 | 10 | Before opening an issue, please search 11 | the [issue tracker](https://github.com/final-form/react-final-form/issues) to 12 | make sure your issue hasn’t already been reported. 13 | 14 | **We use the issue tracker to keep track of bugs and improvements** to 🏁 React 15 | Final Form itself, its examples, and the documentation. We encourage you to open 16 | issues to discuss improvements, architecture, internal implementation, etc. If a 17 | topic has been discussed before, we will ask you to join the previous 18 | discussion. 19 | 20 | For support or usage questions, please search and ask on 21 | [StackOverflow with a `react-final-form` tag](https://stackoverflow.com/questions/tagged/react-final-form). 22 | We ask you to do this because StackOverflow has a much better job at keeping 23 | popular questions visible. Unfortunately good answers get lost and outdated on 24 | GitHub. 25 | 26 | **If you already asked at StackOverflow and still got no answers, post an issue 27 | with the question link, so we can either answer it or evolve into a bug/feature 28 | request.** 29 | 30 | ## Sending a pull request 31 | 32 | **Please ask first before starting work on any significant new features.** 33 | 34 | It's never a fun experience to have your pull request declined after investing a 35 | lot of time and effort into a new feature. To avoid this from happening, we 36 | request that contributors create 37 | [an issue](https://github.com/final-form/react-final-form/issues) to first 38 | discuss any significant new features. 39 | 40 | Please try to keep your pull request focused in scope and avoid including 41 | unrelated commits. 42 | 43 | After you have submitted your pull request, we’ll try to get back to you as soon 44 | as possible. We may suggest some changes or improvements. 45 | 46 | Please format the code before submitting your pull request by running: 47 | 48 | ```sh 49 | npm run precommit 50 | ``` 51 | 52 | ## Coding standards 53 | 54 | Our code formatting rules are defined in 55 | [.eslintrc](https://github.com/final-form/react-final-form/blob/master/.eslintrc). 56 | You can check your code against these standards by running: 57 | 58 | ```sh 59 | npm start lint 60 | ``` 61 | 62 | To automatically fix any style violations in your code, you can run: 63 | 64 | ```sh 65 | npm run precommit 66 | ``` 67 | 68 | ## Running tests 69 | 70 | You can run the test suite using the following commands: 71 | 72 | ```sh 73 | npm test 74 | ``` 75 | 76 | Please ensure that the tests are passing when submitting a pull request. If 77 | you're adding new features to 🏁 React Final Form, please include tests. 78 | -------------------------------------------------------------------------------- /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | # These are supported funding model platforms 2 | 3 | github: erikras 4 | patreon: erikras 5 | open_collective: final-form 6 | ko_fi: # Replace with a single Ko-fi username 7 | tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel 8 | community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry 9 | liberapay: # Replace with a single Liberapay username 10 | issuehunt: # Replace with a single IssueHunt username 11 | otechie: # Replace with a single Otechie username 12 | custom: # Replace with a single custom sponsorship URL 13 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | 6 | 7 | ### Are you submitting a **bug report** or a **feature request**? 8 | 9 | 10 | 11 | ### What is the current behavior? 12 | 13 | 14 | 15 | ### What is the expected behavior? 16 | 17 | ### Sandbox Link 18 | 19 | 20 | 21 | ### What's your environment? 22 | 23 | 24 | 25 | ### Other information 26 | 27 | 28 | -------------------------------------------------------------------------------- /.github/PULL_REQUEST_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | 27 | -------------------------------------------------------------------------------- /.github/workflows/ci.yml: -------------------------------------------------------------------------------- 1 | name: CI 2 | 3 | on: [push] 4 | 5 | jobs: 6 | lint: 7 | name: Lint 8 | runs-on: ubuntu-latest 9 | 10 | steps: 11 | - uses: actions/checkout@v2 12 | - name: Use Node.js ${{ matrix.node_version }} 13 | uses: actions/setup-node@v2 14 | with: 15 | node-version: "22" 16 | - name: Prepare env 17 | run: yarn install --ignore-scripts --frozen-lockfile 18 | - name: Run linter 19 | run: yarn start lint 20 | 21 | prettier: 22 | name: Prettier Check 23 | runs-on: ubuntu-latest 24 | 25 | steps: 26 | - uses: actions/checkout@v2 27 | - name: Use Node.js ${{ matrix.node_version }} 28 | uses: actions/setup-node@v2 29 | with: 30 | node-version: "22" 31 | - name: Prepare env 32 | run: yarn install --ignore-scripts --frozen-lockfile 33 | - name: Run prettier 34 | run: yarn start prettier 35 | 36 | test: 37 | name: Unit Tests 38 | runs-on: ubuntu-latest 39 | 40 | steps: 41 | - uses: actions/checkout@v2 42 | - name: Use Node.js ${{ matrix.node_version }} 43 | uses: actions/setup-node@v2 44 | with: 45 | node-version: "22" 46 | - name: Prepare env 47 | run: yarn install --ignore-scripts --frozen-lockfile 48 | - name: Run unit tests 49 | run: yarn start test 50 | - name: Run code coverage 51 | uses: codecov/codecov-action@v2.1.0 52 | -------------------------------------------------------------------------------- /.github/workflows/lock.yml: -------------------------------------------------------------------------------- 1 | name: "Lock Threads" 2 | 3 | on: 4 | schedule: 5 | - cron: "0 * * * *" 6 | workflow_dispatch: 7 | 8 | permissions: 9 | issues: write 10 | pull-requests: write 11 | 12 | concurrency: 13 | group: lock 14 | 15 | jobs: 16 | action: 17 | runs-on: ubuntu-latest 18 | steps: 19 | - uses: dessant/lock-threads@v3 20 | with: 21 | issue-inactive-days: "365" 22 | issue-lock-reason: "resolved" 23 | pr-inactive-days: "365" 24 | pr-lock-reason: "resolved" 25 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .vscode 2 | *.iml 3 | .nyc_output 4 | coverage 5 | flow-coverage 6 | node_modules 7 | dist 8 | lib 9 | es 10 | npm-debug.log 11 | .DS_Store 12 | .yalc 13 | yalc.lock 14 | -------------------------------------------------------------------------------- /.prettierignore: -------------------------------------------------------------------------------- 1 | coverage 2 | dist 3 | node_modules -------------------------------------------------------------------------------- /.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "trailingComma": "all" 3 | } 4 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | sudo: false 2 | language: node_js 3 | before_install: 4 | - npm install -g npm@6.4.0 5 | cache: 6 | directories: 7 | - node_modules 8 | notifications: 9 | email: false 10 | node_js: 11 | - "10" 12 | - "12" 13 | - "14" 14 | script: 15 | - npm start validate 16 | after_success: 17 | - npx codecov 18 | branches: 19 | only: 20 | - main 21 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017 Erik Rasmussen 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # 🏁 React Final Form 2 | 3 | [![React Final Form](banner.png)](https://final-form.org/react) 4 | 5 | [![Backers on Open Collective](https://opencollective.com/final-form/backers/badge.svg)](#backers) [![Sponsors on Open Collective](https://opencollective.com/final-form/sponsors/badge.svg)](#sponsors) [![NPM Version](https://img.shields.io/npm/v/react-final-form.svg?style=flat)](https://www.npmjs.com/package/react-final-form) 6 | [![NPM Downloads](https://img.shields.io/npm/dm/react-final-form.svg?style=flat)](https://www.npmjs.com/package/react-final-form) 7 | [![Build Status](https://travis-ci.org/final-form/react-final-form.svg?branch=master)](https://travis-ci.org/final-form/react-final-form) 8 | [![codecov.io](https://codecov.io/gh/final-form/react-final-form/branch/master/graph/badge.svg)](https://codecov.io/gh/final-form/react-final-form) 9 | [![styled with prettier](https://img.shields.io/badge/styled_with-prettier-ff69b4.svg)](https://github.com/prettier/prettier) 10 | 11 | ✅ Zero dependencies (that affect your bundle size) 12 | 13 | ✅ Only peer dependencies: React and 14 | [🏁 Final Form](https://github.com/final-form/final-form#-final-form) 15 | 16 | ✅ Opt-in subscriptions - only update on the state you need! 17 | 18 | ✅ 💥 [**3.0k gzipped**](https://bundlephobia.com/result?p=react-final-form) 💥 19 | 20 | --- 21 | 22 | [](https://www.sencha.com/) 23 | 24 | ### React Final Form is sponsored by [Sencha](https://www.sencha.com/). 25 | 26 | Comprehensive JS framework and UI components for building enterprise-grade web apps. 27 | 28 | --- 29 | 30 | ## 💬 [Give Feedback on React Final Form](https://goo.gl/forms/dxdfxKNy64DLb99z2) 💬 31 | 32 | In the interest of making 🏁 React Final Form the best library it can be, we'd love your thoughts and feedback. 33 | 34 | [Take a quick survey](https://goo.gl/forms/dxdfxKNy64DLb99z2). 35 | 36 | --- 37 | 38 | React Final Form is a thin React wrapper for [Final Form](https://final-form.org), which is a subscriptions-based form state management library that uses the [Observer pattern](https://en.wikipedia.org/wiki/Observer_pattern), so only the components that need updating are re-rendered as the form's state changes. 39 | 40 | ## [Getting Started](https://final-form.org/docs/react-final-form/getting-started) 41 | 42 | ## [Philosophy](https://final-form.org/docs/react-final-form/philosophy) 43 | 44 | ## [Examples](https://final-form.org/docs/react-final-form/examples) 45 | 46 | ## [API](https://final-form.org/docs/react-final-form/api) 47 | 48 | ## [FAQ](https://final-form.org/docs/react-final-form/faq) 49 | 50 | 51 | -------------------------------------------------------------------------------- /banner.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/final-form/react-final-form/5a64284e1e10f67dfdf1bbaa549631bf95a742f0/banner.png -------------------------------------------------------------------------------- /docs/HolyJS2018.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/final-form/react-final-form/5a64284e1e10f67dfdf1bbaa549631bf95a742f0/docs/HolyJS2018.gif -------------------------------------------------------------------------------- /docs/ReactAlicante2018.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/final-form/react-final-form/5a64284e1e10f67dfdf1bbaa549631bf95a742f0/docs/ReactAlicante2018.gif -------------------------------------------------------------------------------- /docs/api.md: -------------------------------------------------------------------------------- 1 | # This documentation is meant to be read on [final-form.org](https://final-form.org/docs/react-final-form/api). Links may not work on Github.com. 2 | 3 | # API 4 | 5 | The API for React Final Form consists of three components and three hooks: 6 | 7 | ## Components 8 | 9 | ### [`
`](api/Form) 10 | 11 | A component that surrounds your entire form and manages the form state. It can inject form state and functionality, e.g. a `handleSubmit` function for you to pass to your `` element, via render props. 12 | 13 | ### [``](api/Field) 14 | 15 | A component that lives inside your `` and creates a "field". It register itself with the surrounding `` tag and manages all the state for a particular field, providing input callbacks (e.g. `onBlur`, `onChange`, and `onFocus`) as well as the value of the form and myriad metadata about the state of the field. 16 | 17 | ### [``](api/FormSpy) 18 | 19 | _[Advanced Usage]_ A component that can tap into form-wide state from inside your ``. It's primarily only for advanced usage when form renders are being restricted via the `subscription` prop. 20 | 21 | ## Hooks 22 | 23 | ### [`useField()`](api/useField) 24 | 25 | A hook that will convert any of your components into a `` component, registering with the surrounding `` and providing field state to your component. `useField()` is used internally by ``. 26 | 27 | ### [`useForm()`](api/useForm) 28 | 29 | A hook that will pluck the Final Form [`form` instance](/docs/final-form/types/FormApi) out of context. 30 | 31 | ### [`useFormState()`](api/useFormState) 32 | 33 | A hook that will convert any of your components into a `` component, allowing fine-grained control over subscribing to parts of the form state. 34 | -------------------------------------------------------------------------------- /docs/api/FormSpy.md: -------------------------------------------------------------------------------- 1 | # This documentation is meant to be read on [final-form.org](https://final-form.org/docs/react-final-form/api/FormSpy). Links may not work on Github.com. 2 | 3 | # `` 4 | 5 | ```ts 6 | import { FormSpy } from 'react-final-form' 7 | ``` 8 | 9 | A component that subscribes to form state, and injects both form state and the `form` instance via a render prop. 10 | 11 | The `` will rerender any time the form state it is subscribed to changes. By default it subscribes to _all_ form state. You can control which form state it subscribes to with the `subscription` prop. 12 | 13 | By providing an `onChange` prop, `` can also be used to execute code when a particular part of form state changes. 14 | 15 | ## Props 16 | 17 | `` accepts [`FormSpyProps`](../types/FormSpyProps) and will call the render function with [`FormSpyRenderProps`](../types/FormSpyRenderProps). 18 | 19 | The only required prop is one of `onChange`, `component`, `render`, or `children`. 20 | 21 | ## Basic Usage 22 | 23 | It should be noted that `` is for very advanced use cases. 24 | 25 | **If you are not restricting your form state by providing a `subscription` prop to ``, you probably do not need ``!** Just use the form state injected by ``. 26 | 27 | You need to do _one_ of two things when using ``: 28 | 29 | ### 1. Provide a way to render the form state 30 | 31 | There are three ways to render a `` component: 32 | 33 | | Prop | Type | 34 | | ---------------------- | --------------------- | 35 | | `` | `React.ComponentType` | 36 | | `` | `Function` | 37 | | `` | `Function` | 38 | 39 | The only important distinction is that if you pass a `component` prop, it will be rendered with [`React.createElement()`](https://reactjs.org/docs/react-api.html#createelement), resulting in your component actually being in the React node tree, i.e. inspectable in [DevTools](https://github.com/facebook/react-devtools#react-developer-tools-). 40 | 41 | ```tsx 42 | // Render a reset button that will be 43 | // disabled when the form is pristine 44 | 45 | {props => ( 46 | 53 | )} 54 | 55 | ``` 56 | 57 | ### 2. Pass an `onChange` callback 58 | 59 | `` can sometimes be useful to execute code when a particular part of form state changes. This is what the `onChange` callback is for. 60 | 61 | **If you pass `onChange`, nothing will be rendered.** 62 | 63 | ```tsx 64 | { 67 | console.log('Form validity changed to', props.valid) 68 | }} 69 | /> 70 | ``` 71 | -------------------------------------------------------------------------------- /docs/api/useField.md: -------------------------------------------------------------------------------- 1 | # This documentation is meant to be read on [final-form.org](https://final-form.org/docs/react-final-form/api/useField). Links may not work on Github.com. 2 | 3 | # `useField()` 4 | 5 | ```ts 6 | import { useField } from 'react-final-form' 7 | ``` 8 | 9 | 10 | ```ts 11 | (name: string, config: UseFieldConfig) => FieldRenderProps 12 | ``` 13 | 14 | The `useField()` hook takes two parameters: 15 | 16 | ### `name` 17 | 18 | ```ts 19 | string 20 | ``` 21 | 22 | **Required** 23 | 24 | The name of the field. 25 | 26 | ### `config` 27 | 28 | ```ts 29 | UseFieldConfig 30 | ``` 31 | 32 | Optional. 33 | 34 | An object that looks just like [`FieldProps`](../types/FieldProps), except without the name. 35 | 36 | `useField()` returns [`FieldRenderProps`](../types/FieldRenderProps). It will manage the rerendering of any component you use it in, i.e. the component will only rerender if the field state subscribed to via `useField()` changes. 37 | 38 | `useField()` is used internally inside [``](Field). 39 | -------------------------------------------------------------------------------- /docs/api/useForm.md: -------------------------------------------------------------------------------- 1 | # This documentation is meant to be read on [final-form.org](https://final-form.org/docs/react-final-form/api/useForm). Links may not work on Github.com. 2 | 3 | # `useForm()` 4 | 5 | ```ts 6 | import { useForm } from 'react-final-form' 7 | ``` 8 | 9 | 10 | ```ts 11 | () => FormApi 12 | ``` 13 | 14 | The `useForm()` hook plucks the [`FormApi`](/docs/final-form/types/FormApi) out of the React context for you. It will throw an exception if you try to use it outside of a [``](Form) component. 15 | 16 | `useForm()` is used internally inside [`useField()`](useField), [``](Field), and [``](FormSpy). 17 | -------------------------------------------------------------------------------- /docs/api/useFormState.md: -------------------------------------------------------------------------------- 1 | # This documentation is meant to be read on [final-form.org](https://final-form.org/docs/react-final-form/api/useFormState). Links may not work on Github.com. 2 | 3 | # `useFormState` 4 | 5 | ```ts 6 | import { useFormState } from 'react-final-form' 7 | ``` 8 | 9 | The `useFormState()` hook takes one optional parameter, which matches the exact shape of [`FormSpyProps`](../types/FormSpyProps) (except without the render props). It returns a [`FormState`](/docs/final-form/types/FormState). 10 | 11 | `useFormState()` is used internally inside [``](FormSpy). 12 | -------------------------------------------------------------------------------- /docs/examples/chakra.md: -------------------------------------------------------------------------------- 1 | # This documentation is meant to be read on [final-form.org](https://final-form.org/docs/react-final-form/examples/chakra). Links may not work on Github.com. 2 | 3 | # Chakra UI Example 4 | 5 | Demonstrates how to use [Chakra UI](https://chakra-ui.com) components with React Final Form. 6 | 7 | [![Edit react-final-form-chakra-example](https://codesandbox.io/static/img/play-codesandbox.svg)](https://codesandbox.io/s/github/final-form/react-final-form/tree/master/examples/chakra) 8 | -------------------------------------------------------------------------------- /docs/examples/field-level-validation.md: -------------------------------------------------------------------------------- 1 | # This documentation is meant to be read on [final-form.org](https://final-form.org/docs/react-final-form/examples/field-level-validation). Links may not work on Github.com. 2 | 3 | # Field Level Validation Example 4 | 5 | Introduces field-level validation functions and demonstrates how to display errors next to fields using child render functions. 6 | 7 | [![Edit react-final-form-field-level-validation-example](https://codesandbox.io/static/img/play-codesandbox.svg)](https://codesandbox.io/s/github/final-form/react-final-form/tree/master/examples/field-level-validation) 8 | -------------------------------------------------------------------------------- /docs/examples/record-level-validation.md: -------------------------------------------------------------------------------- 1 | # This documentation is meant to be read on [final-form.org](https://final-form.org/docs/react-final-form/examples/record-level-validation). Links may not work on Github.com. 2 | 3 | # Record-Level Example 4 | 5 | Introduces a whole-record validation function and demonstrates how to display errors next to fields using child render functions. 6 | 7 | [![Edit react-final-form-record-level-validation](https://codesandbox.io/static/img/play-codesandbox.svg)](https://codesandbox.io/s/github/final-form/react-final-form/tree/master/examples/record-level-validation) 8 | -------------------------------------------------------------------------------- /docs/examples/simple.md: -------------------------------------------------------------------------------- 1 | # This documentation is meant to be read on [final-form.org](https://final-form.org/docs/react-final-form/examples/simple). Links may not work on Github.com. 2 | 3 | # Simple Example 4 | 5 | Uses the built-in React inputs: input, select, and textarea to build a form with no validation. 6 | 7 | [![Edit react-final-form-simple-example](https://codesandbox.io/static/img/play-codesandbox.svg)](https://codesandbox.io/s/github/final-form/react-final-form/tree/master/examples/simple) 8 | -------------------------------------------------------------------------------- /docs/examples/submission-errors.md: -------------------------------------------------------------------------------- 1 | # This documentation is meant to be read on [final-form.org](https://final-form.org/docs/react-final-form/examples/submission-errors). Links may not work on Github.com. 2 | 3 | # Submission Errors 4 | 5 | Demonstrates how to return submission errors from failed submits. Notice that the `Promise` should _resolve_ to the submission error (not reject). Rejection is reserved for communications or server exceptions. 6 | 7 | [![Edit react-final-form-submission-errors-example](https://codesandbox.io/static/img/play-codesandbox.svg)](https://codesandbox.io/s/github/final-form/react-final-form/tree/master/examples/submission-errors) 8 | -------------------------------------------------------------------------------- /docs/examples/subscriptions.md: -------------------------------------------------------------------------------- 1 | # This documentation is meant to be read on [final-form.org](https://final-form.org/docs/react-final-form/examples/subscriptions). Links may not work on Github.com. 2 | 3 | # High Performance Through Subscriptions Example 4 | 5 | Demonstrates how, by restricting which parts of form state the form component needs to render, it reduces the number of times the whole form has to rerender. Yet, if some part of form state is needed inside of it, the [``](../api/FormSpy) component can be used to attain it. 6 | 7 | [![Edit react-final-form-subscriptions-example](https://codesandbox.io/static/img/play-codesandbox.svg)](https://codesandbox.io/s/github/final-form/react-final-form/tree/master/examples/subscriptions) 8 | -------------------------------------------------------------------------------- /docs/examples/wizard.md: -------------------------------------------------------------------------------- 1 | # This documentation is meant to be read on [final-form.org](https://final-form.org/docs/react-final-form/examples/wizard). Links may not work on Github.com. 2 | 3 | # Wizard Form Example 4 | 5 | Demonstrates how to use React Final Form to create a multi-page "wizard" form, with validation on each page. 6 | 7 | [![Edit react-final-form-wizard-example](https://codesandbox.io/static/img/play-codesandbox.svg)](https://codesandbox.io/s/github/final-form/react-final-form/tree/master/examples/wizard) 8 | -------------------------------------------------------------------------------- /docs/getting-started.md: -------------------------------------------------------------------------------- 1 | # This documentation is meant to be read on [final-form.org](https://final-form.org/docs/react-final-form/getting-started). Links may not work on Github.com. 2 | 3 | # Getting Started 4 | 5 | Before we jump right into code, you might want to learn a little bit about the [philosophy](philosophy) and origin story of React Final Form. 6 | 7 | ## Installation 8 | 9 | ```bash 10 | npm install --save final-form react-final-form 11 | ``` 12 | 13 | or 14 | 15 | ```bash 16 | yarn add final-form react-final-form 17 | ``` 18 | 19 | ## Architecture 20 | 21 | React Final Form is a thin React wrapper for [Final Form](/), which is a subscriptions-based form state management library that uses the [Observer pattern](https://en.wikipedia.org/wiki/Observer_pattern), so only the components that need updating are re-rendered as the form's state changes. 22 | 23 | By default, **React Final Form subscribes to _all_ changes**, but if you want to fine tune your form to optimized blazing-fast perfection, you may specify only the form state that you care about for rendering your gorgeous UI. You can think of it a little like GraphQL's feature of only fetching the data your component needs to render, and nothing else. 24 | 25 | ## Code 26 | 27 | Here's what it looks like in your code: 28 | 29 | ```jsx 30 | import { Form, Field } from 'react-final-form' 31 | 32 | const MyForm = () => ( 33 | ( 37 | 38 |

Simple Default Input

39 |
40 | 41 | 42 |
43 | 44 |

An Arbitrary Reusable Input Component

45 |
46 | 47 | 48 |
49 | 50 |

Render Function

51 | ( 54 |
55 | 56 |