Skip to content

Commit e036c2a

Browse files
authored
Added decorator support (#47)
1 parent c8eb275 commit e036c2a

File tree

5 files changed

+78
-17
lines changed

5 files changed

+78
-17
lines changed

README.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -158,6 +158,7 @@ const MyForm = () => (
158158
* [`children?: ((props: FormRenderProps) => React.Node) | React.Node`](#children-props-formrenderprops--reactnode--reactnode)
159159
* [`component?: React.ComponentType<FormRenderProps>`](#component-reactcomponenttypeformrenderprops)
160160
* [`debug?: DebugFunction`](#debug-debugfunction)
161+
* [`decorators?: Decorator[]`](#decorators-decorator)
161162
* [`initialValues?: Object`](#initialvalues-object)
162163
* [`mutators?: { [string]: Mutator }`](#mutators--string-mutator-)
163164
* [`onSubmit: (values: Object, callback: ?(errors: ?Object) => void) => ?Object | Promise<?Object> | void`](#onsubmit-values-object-callback-errors-object--void--object--promiseobject--void)
@@ -448,6 +449,11 @@ well as any non-API props passed into the `<Form/>` component.
448449

449450
[See the 🏁 Final Form docs on `debug`](https://github.com/final-form/final-form#debug-debugfunction).
450451

452+
#### `decorators?: Decorator[]`
453+
454+
[`Decorator`](https://github.com/final-form/final-form#decorator-form-formapi--unsubscribe)s
455+
to apply to the form.
456+
451457
#### `initialValues?: Object`
452458

453459
[See the 🏁 Final Form docs on `initialValues`](https://github.com/final-form/final-form#initialvalues-object).

package.json

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "react-final-form",
3-
"version": "1.1.1",
3+
"version": "1.2.0",
44
"description":
55
"🏁 High performance subscription-based form state management for React",
66
"main": "dist/react-final-form.cjs.js",
@@ -40,7 +40,7 @@
4040
"eslint-plugin-import": "^2.8.0",
4141
"eslint-plugin-jsx-a11y": "^6.0.2",
4242
"eslint-plugin-react": "^7.4.0",
43-
"final-form": "^1.2.0",
43+
"final-form": "^1.3.0",
4444
"flow": "^0.2.3",
4545
"flow-bin": "^0.60.1",
4646
"husky": "^0.14.3",
@@ -63,7 +63,7 @@
6363
"rollup-plugin-uglify": "^2.0.1"
6464
},
6565
"peerDependencies": {
66-
"final-form": "^1.2.0",
66+
"final-form": "^1.3.0",
6767
"prop-types": "^15.6.0",
6868
"react": "^15.0.0-0 || ^16.0.0-0"
6969
},

src/ReactFinalForm.js

Lines changed: 28 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -7,11 +7,17 @@ import {
77
formSubscriptionItems,
88
version as ffVersion
99
} from 'final-form'
10-
import type { Api, Config, FormSubscription, FormState } from 'final-form'
10+
import type {
11+
Api,
12+
Config,
13+
FormSubscription,
14+
FormState,
15+
Unsubscribe
16+
} from 'final-form'
1117
import type { FormProps as Props, ReactContext } from './types'
1218
import shallowEqual from './shallowEqual'
1319
import renderComponent from './renderComponent'
14-
export const version = '1.0.0'
20+
export const version = '1.2.0'
1521

1622
export const all: FormSubscription = formSubscriptionItems.reduce(
1723
(result, key) => {
@@ -30,7 +36,7 @@ export default class ReactFinalForm extends React.PureComponent<Props, State> {
3036
props: Props
3137
state: State
3238
form: Api
33-
unsubscribe: () => void
39+
unsubscriptions: Unsubscribe[]
3440

3541
static childContextTypes = {
3642
reactFinalForm: PropTypes.object
@@ -44,6 +50,7 @@ export default class ReactFinalForm extends React.PureComponent<Props, State> {
4450
children,
4551
component,
4652
debug,
53+
decorators,
4754
initialValues,
4855
mutators,
4956
onSubmit,
@@ -70,16 +77,24 @@ export default class ReactFinalForm extends React.PureComponent<Props, State> {
7077
warning(false, e.message)
7178
}
7279
let initialState
73-
this.unsubscribe =
74-
this.form &&
75-
this.form.subscribe((state: FormState) => {
76-
if (initialState) {
77-
this.notify(state)
78-
} else {
79-
initialState = state
80-
}
81-
}, subscription || all)
80+
this.unsubscriptions = []
81+
if (this.form) {
82+
this.unsubscriptions.push(
83+
this.form.subscribe((state: FormState) => {
84+
if (initialState) {
85+
this.notify(state)
86+
} else {
87+
initialState = state
88+
}
89+
}, subscription || all)
90+
)
91+
}
8292
this.state = { state: initialState }
93+
if (decorators) {
94+
decorators.forEach(decorator => {
95+
this.unsubscriptions.push(decorator(this.form))
96+
})
97+
}
8398
}
8499

85100
getChildContext() {
@@ -102,7 +117,7 @@ export default class ReactFinalForm extends React.PureComponent<Props, State> {
102117
}
103118

104119
componentWillUnmount() {
105-
this.unsubscribe()
120+
this.unsubscriptions.forEach(unsubscribe => unsubscribe())
106121
}
107122

108123
render() {

src/ReactFinalForm.test.js

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -317,4 +317,42 @@ describe('ReactFinalForm', () => {
317317
expect(validate).toHaveBeenCalledTimes(4)
318318
expect(renderInput).toHaveBeenCalledTimes(2)
319319
})
320+
321+
it('should add decorators', () => {
322+
const unsubscribe = jest.fn()
323+
const decorator = jest.fn(() => unsubscribe)
324+
class Container extends React.Component {
325+
state = { shown: true }
326+
327+
render() {
328+
return (
329+
<div>
330+
{this.state.shown && (
331+
<Form
332+
onSubmit={onSubmitMock}
333+
render={() => <form />}
334+
decorators={[decorator]}
335+
/>
336+
)}
337+
<button
338+
type="button"
339+
onClick={() => this.setState({ shown: false })}
340+
>
341+
Unmount
342+
</button>
343+
</div>
344+
)
345+
}
346+
}
347+
const dom = TestUtils.renderIntoDocument(<Container />)
348+
349+
expect(decorator).toHaveBeenCalled()
350+
expect(decorator).toHaveBeenCalledTimes(1)
351+
expect(unsubscribe).not.toHaveBeenCalled()
352+
353+
const button = TestUtils.findRenderedDOMComponentWithTag(dom, 'button')
354+
TestUtils.Simulate.click(button)
355+
356+
expect(unsubscribe).toHaveBeenCalled()
357+
})
320358
})

src/types.js.flow

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import * as React from 'react'
33
import type {
44
Api,
55
Config,
6+
Decorator,
67
FormState,
78
FormSubscription,
89
FieldSubscription
@@ -55,7 +56,8 @@ export type RenderableProps<T> = $Shape<{
5556
}>
5657

5758
export type FormProps = {
58-
subscription?: FormSubscription
59+
subscription?: FormSubscription,
60+
decorators?: Decorator[]
5961
} & Config &
6062
RenderableProps<FormRenderProps>
6163

0 commit comments

Comments
 (0)