Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

if name prop is passed as undefined to Field component, an error is t… #777

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions src/Field.js
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,11 @@ const Field = ({
// ignore meta, combine input with any other props
return React.createElement(component, { ...field.input, children, ...rest })
}

if (!name) {
throw new Error('prop name cannot be undefined in <Field> component')
}

return renderComponent(
{ children, component, ...rest },
field,
Expand Down
66 changes: 43 additions & 23 deletions src/Field.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,9 @@ import { ErrorBoundary, Toggle, wrapWith } from './testUtils'
import Form from './ReactFinalForm'
import Field from './Field'

const onSubmitMock = values => {}
const onSubmitMock = (values) => {}

const timeout = ms => new Promise(resolve => setTimeout(resolve, ms))
const timeout = (ms) => new Promise((resolve) => setTimeout(resolve, ms))
async function sleep(ms) {
await act(async () => {
await timeout(ms)
Expand Down Expand Up @@ -36,7 +36,7 @@ describe('Field', () => {
it('should resubscribe if name changes', () => {
const { getByTestId, getByText } = render(
<Toggle>
{isCat => (
{(isCat) => (
<Form
onSubmit={onSubmitMock}
initialValues={{ dog: 'Odie', cat: 'Garfield' }}
Expand Down Expand Up @@ -129,7 +129,7 @@ describe('Field', () => {
// This is mainly here for code coverage. 🧐
const { getByText } = render(
<Toggle>
{hidden => (
{(hidden) => (
<Form
onSubmit={onSubmitMock}
initialValues={{ dog: 'Odie', cat: 'Garfield' }}
Expand Down Expand Up @@ -208,7 +208,7 @@ describe('Field', () => {
<Form onSubmit={onSubmitMock} subscription={{ values: true }}>
{wrapWith(spy, () => (
<form>
<Field name="name" parse={v => v}>
<Field name="name" parse={(v) => v}>
{({ input: { value, ...props } }) => (
<input
{...props}
Expand Down Expand Up @@ -241,7 +241,7 @@ describe('Field', () => {
<Field
name="name"
component="input"
format={value => (value ? value.toUpperCase() : '')}
format={(value) => (value ? value.toUpperCase() : '')}
data-testid="name"
/>
</form>
Expand All @@ -258,7 +258,7 @@ describe('Field', () => {
})

it('should only format on blur if formatOnBlur is true', () => {
const format = jest.fn(value => (value ? value.toUpperCase() : ''))
const format = jest.fn((value) => (value ? value.toUpperCase() : ''))
const { getByTestId } = render(
<Form onSubmit={onSubmitMock} subscription={{ values: true }}>
{() => (
Expand Down Expand Up @@ -286,7 +286,7 @@ describe('Field', () => {
})

it('should `formatOnBlur` most updated value', () => {
const format = jest.fn(value => (value ? value.trim() : ''))
const format = jest.fn((value) => (value ? value.trim() : ''))
const { getByTestId } = render(
<Form onSubmit={onSubmitMock} subscription={{ values: true }}>
{() => (
Expand All @@ -296,7 +296,7 @@ describe('Field', () => {
<input
{...input}
data-testid="name"
onBlur={e => {
onBlur={(e) => {
input.onChange(
e.target.value && e.target.value.toUpperCase()
)
Expand All @@ -320,7 +320,7 @@ describe('Field', () => {
})

it('should not format value at all when formatOnBlur and render prop', () => {
const format = jest.fn(value => (value ? value.toUpperCase() : ''))
const format = jest.fn((value) => (value ? value.toUpperCase() : ''))
render(
<Form onSubmit={onSubmitMock} subscription={{ values: true }}>
{() => (
Expand All @@ -344,7 +344,7 @@ describe('Field', () => {
<Form onSubmit={onSubmitMock} subscription={{ values: true }}>
{() => (
<form>
<Field name="name" format={v => v}>
<Field name="name" format={(v) => v}>
{wrapWith(spy, ({ input: { value, ...props } }) => (
<input
{...props}
Expand Down Expand Up @@ -535,8 +535,8 @@ describe('Field', () => {
})

it('should allow changing field-level validation function', () => {
const simpleValidate = value => (value ? undefined : 'Required')
const complexValidate = value => {
const simpleValidate = (value) => (value ? undefined : 'Required')
const complexValidate = (value) => {
if (value) {
if (value !== value.toUpperCase()) {
return 'SHOULD BE UPPERCASE!'
Expand All @@ -547,7 +547,7 @@ describe('Field', () => {
}
const { getByTestId, getByText } = render(
<Toggle>
{useComplexValidation => (
{(useComplexValidation) => (
<Form onSubmit={onSubmitMock}>
{({ handleSubmit }) => (
<form onSubmit={handleSubmit}>
Expand Down Expand Up @@ -594,8 +594,8 @@ describe('Field', () => {
* form.
*/
it('should ignore changes field-level validation function', () => {
const createValidator = isRequired =>
isRequired ? value => (value ? undefined : 'Required') : undefined
const createValidator = (isRequired) =>
isRequired ? (value) => (value ? undefined : 'Required') : undefined

const Error = ({ name }) => (
<Field name={name} subscription={{ error: true }}>
Expand All @@ -604,7 +604,7 @@ describe('Field', () => {
)
const { getByTestId, getByText } = render(
<Toggle>
{isRequired => (
{(isRequired) => (
<Form onSubmit={onSubmitMock}>
{({ handleSubmit }) => (
<form onSubmit={handleSubmit}>
Expand Down Expand Up @@ -640,7 +640,7 @@ describe('Field', () => {

it('should not rerender if validateFields is !== every time', () => {
// https://github.com/final-form/react-final-form/issues/502
const required = value => (value ? undefined : 'Required')
const required = (value) => (value ? undefined : 'Required')
const spy = jest.fn()
const { getByTestId } = render(
<Form onSubmit={onSubmitMock}>
Expand Down Expand Up @@ -1022,7 +1022,7 @@ describe('Field', () => {
<Field
name="name"
component="input"
format={value => value && value.toUpperCase()}
format={(value) => value && value.toUpperCase()}
formatOnBlur
data-testid="name"
/>
Expand Down Expand Up @@ -1091,7 +1091,7 @@ describe('Field', () => {
<Field
name="name"
component="input"
validate={async value => {
validate={async (value) => {
await timeout(5)
return value === 'erikras' ? 'Username taken' : undefined
}}
Expand Down Expand Up @@ -1136,7 +1136,7 @@ describe('Field', () => {
const validate = jest.fn()
const { getByText } = render(
<Toggle>
{showOtherFields => (
{(showOtherFields) => (
<Form onSubmit={onSubmitMock} validate={validate}>
{({ handleSubmit }) => (
<form onSubmit={handleSubmit}>
Expand Down Expand Up @@ -1168,13 +1168,13 @@ describe('Field', () => {
it('submit should not throw when field with enabled `formatOnBlur` changes name `prop`', () => {
const onSubmit = jest.fn()

const trim = value => value && value.trim()
const trim = (value) => value && value.trim()

const { getByTestId, getByText } = render(
<Form onSubmit={onSubmit}>
{({ handleSubmit }) => (
<Toggle>
{newFieldName => (
{(newFieldName) => (
<form onSubmit={handleSubmit}>
<Field
name={newFieldName ? 'newName' : 'oldName'}
Expand All @@ -1199,4 +1199,24 @@ describe('Field', () => {
expect(onSubmit).toHaveBeenCalled()
expect(onSubmit.mock.calls[0][0]).toEqual({ newName: 'trailing space' })
})

it('should throw an error if name prop is undefined', () => {
jest.spyOn(console, 'error').mockImplementation(() => {})

const errorSpy = jest.fn()
render(
<ErrorBoundary spy={errorSpy}>
<Form onSubmit={onSubmitMock}>
{() => <Field name={undefined} render={() => <input />} />}
</Form>
</ErrorBoundary>
)

expect(errorSpy).toHaveBeenCalled()
expect(errorSpy).toHaveBeenCalledTimes(1)
expect(errorSpy.mock.calls[0][0].message).toBe(
'prop name cannot be undefined in <Field> component'
)
console.error.mockRestore()
})
})