Skip to content

Commit 4e72442

Browse files
Andaristerikras
authored andcommitted
Make flattenSubscription hooks-safe (#479)
1 parent 6054da7 commit 4e72442

5 files changed

+26
-26
lines changed

src/ReactFinalForm.js

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ const ReactFinalForm = ({
4646
keepDirtyOnReinitialize,
4747
mutators,
4848
onSubmit,
49-
subscription,
49+
subscription = all,
5050
validate,
5151
validateOnBlur,
5252
...rest
@@ -74,14 +74,13 @@ const ReactFinalForm = ({
7474
let initialState: FormState = {}
7575
form.subscribe(state => {
7676
initialState = state
77-
}, subscription || all)()
77+
}, subscription)()
7878
return initialState
7979
}
8080
)
8181

82-
// ⚠️ flattenedSubscription is probably not "hook-safe".
8382
// In the future, changing subscriptions on the fly should be banned. ⚠️
84-
const flattenedSubscription = flattenSubscription(subscription || all)
83+
const flattenedSubscription = flattenSubscription(subscription)
8584
React.useEffect(() => {
8685
// We have rendered, so all fields are no registered, so we can unpause validation
8786
form.isValidationPaused() && form.resumeValidation()
@@ -90,7 +89,7 @@ const ReactFinalForm = ({
9089
if (!shallowEqual(s, state)) {
9190
setState(s)
9291
}
93-
}, subscription || all),
92+
}, subscription),
9493
...(decorators
9594
? decorators.map(decorator =>
9695
// this noop ternary is to appease the flow gods
@@ -104,7 +103,7 @@ const ReactFinalForm = ({
104103
unsubscriptions.forEach(unsubscribe => unsubscribe())
105104
}
106105
// eslint-disable-next-line react-hooks/exhaustive-deps
107-
}, [decorators, ...flattenedSubscription])
106+
}, [decorators, flattenedSubscription])
108107

109108
// warn about decorator changes
110109
// istanbul ignore next

src/flattenSubscription.js

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,10 @@
22
type Subscription = { [string]: boolean }
33
export default function flattenSubscription(
44
subscription: Subscription = {}
5-
): string[] {
6-
return Object.keys(subscription).filter(key => subscription[key] === true)
5+
): string {
6+
return Object.keys(subscription)
7+
.filter(key => subscription[key] === true)
8+
.map(key => key)
9+
.sort()
10+
.join(',')
711
}

src/flattenSubscription.test.js

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,15 +2,14 @@ import flattenSubscription from './flattenSubscription'
22

33
describe('flattenSubscription', () => {
44
it('should return empty array when subscription is empty', () => {
5-
expect(flattenSubscription(undefined)).toEqual([])
6-
expect(flattenSubscription({})).toEqual([])
5+
expect(flattenSubscription(undefined)).toEqual('')
6+
expect(flattenSubscription({})).toEqual('')
77
})
88

99
it('should return only keys that are true in subscription', () => {
10-
expect(flattenSubscription({ foo: true, bar: false })).toEqual(['foo'])
11-
expect(flattenSubscription({ foo: true, bar: true, baz: false })).toEqual([
12-
'foo',
13-
'bar'
14-
])
10+
expect(flattenSubscription({ foo: true, bar: false })).toEqual('foo')
11+
expect(flattenSubscription({ foo: true, bar: true, baz: false })).toEqual(
12+
'bar,foo'
13+
)
1514
})
1615
})

src/useField.js

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ const useField = (
3232
isEqual,
3333
multiple,
3434
parse = defaultParse,
35-
subscription,
35+
subscription = all,
3636
type,
3737
validate,
3838
validateFields,
@@ -49,7 +49,7 @@ const useField = (
4949

5050
const beforeSubmitRef = React.useRef()
5151
const register = (callback: FieldState => void) =>
52-
form.registerField(name, callback, subscription || all, {
52+
form.registerField(name, callback, subscription, {
5353
afterSubmit,
5454
beforeSubmit: () => beforeSubmitRef.current && beforeSubmitRef.current(),
5555
defaultValue,
@@ -82,9 +82,8 @@ const useField = (
8282
return beforeSubmit && beforeSubmit()
8383
}
8484

85-
// ⚠️ flattenedSubscription is probably not "hook-safe".
8685
// In the future, changing subscriptions on the fly should be banned. ⚠️
87-
const flattenedSubscription = flattenSubscription(subscription || all)
86+
const flattenedSubscription = flattenSubscription(subscription)
8887
React.useEffect(
8988
() =>
9089
register(state => {
@@ -105,7 +104,7 @@ const useField = (
105104
isEqual,
106105
validateFields,
107106
// eslint-disable-next-line react-hooks/exhaustive-deps
108-
...flattenedSubscription
107+
flattenedSubscription
109108
]
110109
)
111110

src/useFormState.js

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ import useForm from './useForm'
88

99
const useFormState = ({
1010
onChange,
11-
subscription
11+
subscription = all
1212
}: UseFormStateParams = {}): FormState => {
1313
const form: FormApi = useForm('useFormState')
1414
const firstRender = React.useRef(true)
@@ -19,17 +19,16 @@ const useFormState = ({
1919
let initialState: FormState = {}
2020
form.subscribe(state => {
2121
initialState = state
22-
}, subscription || all)()
22+
}, subscription)()
2323
if (onChange) {
2424
onChange(initialState)
2525
}
2626
return initialState
2727
}
2828
)
2929

30-
// ⚠️ flattenedSubscription is probably not "hook-safe".
3130
// In the future, changing subscriptions on the fly should be banned. ⚠️
32-
const flattenedSubscription = flattenSubscription(subscription || all)
31+
const flattenedSubscription = flattenSubscription(subscription)
3332
React.useEffect(
3433
() =>
3534
form.subscribe(newState => {
@@ -41,9 +40,9 @@ const useFormState = ({
4140
onChange(newState)
4241
}
4342
}
44-
}, subscription || all),
43+
}, subscription),
4544
// eslint-disable-next-line react-hooks/exhaustive-deps
46-
flattenedSubscription
45+
[flattenedSubscription]
4746
)
4847
return state
4948
}

0 commit comments

Comments
 (0)