From 511216b6e48c66469b46cf4b1317ddc07c2f0d6f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateusz=20Burzy=C5=84ski?= Date: Tue, 27 Mar 2018 20:48:18 +0200 Subject: [PATCH] Add dev warning when type prop is missed for checkbox, radio or multiple select --- src/Field.js | 27 ++++++++++++++++++-- src/Field.test.js | 64 +++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 89 insertions(+), 2 deletions(-) diff --git a/src/Field.js b/src/Field.js index ba256991..fa0254e3 100644 --- a/src/Field.js +++ b/src/Field.js @@ -100,6 +100,30 @@ export default class Field extends React.Component { }, onChange: (event: SyntheticInputEvent<*> | any) => { const { parse, value: _value } = this.props + + if (process.env.NODE_ENV !== 'production' && event && event.target) { + const targetType = event.target.type + const props: Object = this.props + const unknown = + ~['checkbox', 'radio', 'select-multiple'].indexOf(targetType) && + !props.type + + const type = targetType === 'select-multiple' ? 'select' : targetType + const { value }: any = + targetType === 'select-multiple' ? this.state.state || {} : props + + if (unknown) { + console.error( + `Warning: You must pass \`type="${type}"\` prop to your Field(${ + props.name + }) component.\n` + + `Without it we don't know how to unpack your \`value\` prop - ${ + Array.isArray(value) ? `[${value}]` : `"${value}"` + }.` + ) + } + } + const value: any = event && event.target ? getValue( @@ -151,8 +175,7 @@ export default class Field extends React.Component { } else if ((rest: Object).type === 'radio') { input.checked = value === _value input.value = _value - } - if (component === 'select' && (rest: Object).multiple) { + } else if (component === 'select' && (rest: Object).multiple) { input.value = input.value || [] } diff --git a/src/Field.test.js b/src/Field.test.js index 77b43648..a6112ac3 100644 --- a/src/Field.test.js +++ b/src/Field.test.js @@ -706,4 +706,68 @@ describe('Field', () => { expect(barValidate).toHaveBeenCalledTimes(1) expect(bazValidate).toHaveBeenCalledTimes(1) }) + + it('should warn when used without type prop and rendering radio, checkbox or multiple select indirectly', () => { + class Container extends React.Component { + render() { + return ( +
{}}> + {() => ( +
+ + {({ input }) => } + + + {({ input }) => } + + + {({ input }) => ( + + )} + +
+ )} +
+ ) + } + } + + const spy = jest.spyOn(global.console, 'error').mockImplementation(() => {}) + const dom = TestUtils.renderIntoDocument() + + const [checkbox, radio] = TestUtils.scryRenderedDOMComponentsWithTag( + dom, + 'input' + ) + const [select] = TestUtils.scryRenderedDOMComponentsWithTag(dom, 'select') + + TestUtils.Simulate.change(checkbox, { + target: { type: 'checkbox', value: 'checkbox_value' } + }) + TestUtils.Simulate.change(radio, { + target: { type: 'radio', value: 'radio_value' } + }) + TestUtils.Simulate.change(select, { + target: { type: 'select-multiple', value: ['select_value'] } + }) + + expect(spy).toHaveBeenCalled() + expect(spy).toHaveBeenCalledTimes(3) + expect(spy.mock.calls[0][0]).toBe( + 'Warning: You must pass `type="checkbox"` prop to your Field(checkbox_test) component.\n' + + 'Without it we don\'t know how to unpack your `value` prop - "checkbox_value".' + ) + expect(spy.mock.calls[1][0]).toBe( + 'Warning: You must pass `type="radio"` prop to your Field(radio_test) component.\n' + + 'Without it we don\'t know how to unpack your `value` prop - "radio_value".' + ) + expect(spy.mock.calls[2][0]).toBe( + 'Warning: You must pass `type="select"` prop to your Field(select_test) component.\n' + + "Without it we don't know how to unpack your `value` prop - []." + ) + + spy.mockRestore() + }) })