Skip to content

Commit

Permalink
Change how form wide errors stored in the state
Browse files Browse the repository at this point in the history
  • Loading branch information
unconfident committed Jan 9, 2018
1 parent f23a36e commit ac752d3
Show file tree
Hide file tree
Showing 5 changed files with 89 additions and 40 deletions.
62 changes: 42 additions & 20 deletions src/createReducer.js
Original file line number Diff line number Diff line change
Expand Up @@ -222,8 +222,11 @@ function createReducer<M, L>(structure: Structure<M, L>) {
result = setIn(result, `values.${field}`, payload)
}
result = deleteInWithCleanUp(result, `asyncErrors.${field}`)
if (!persistentSubmitErrors) {
if (persistentSubmitErrors) {
result = setIn(result, `submitErrorsUpToDate`, false)
} else {
result = deleteInWithCleanUp(result, `submitErrors.${field}`)
result = deleteIn(result, `submitErrorsUpToDate`)
}
result = deleteInWithCleanUp(result, `fields.${field}.autofilled`)
if (touch) {
Expand All @@ -238,7 +241,8 @@ function createReducer<M, L>(structure: Structure<M, L>) {
[CLEAR_SUBMIT_ERRORS](state) {
let result = state
result = deleteInWithCleanUp(result, 'submitErrors')
result = deleteIn(result, 'error')
result = deleteIn(result, 'submitFormWideError')
result = deleteIn(result, `submitErrorsUpToDate`)
return result
},
[CLEAR_ASYNC_ERROR](state, { meta: { field } }) {
Expand All @@ -252,8 +256,11 @@ function createReducer<M, L>(structure: Structure<M, L>) {
fields.forEach(field => {
result = deleteInWithCleanUp(result, `values.${field}`)
result = deleteInWithCleanUp(result, `asyncErrors.${field}`)
if (!persistentSubmitErrors) {
if (persistentSubmitErrors) {
result = setIn(result, `submitErrorsUpToDate`, false)
} else {
result = deleteInWithCleanUp(result, `submitErrors.${field}`)
result = deleteIn(result, `submitErrorsUpToDate`)
}
result = deleteInWithCleanUp(result, `fields.${field}.autofilled`)
if (!keepTouched) {
Expand All @@ -277,7 +284,13 @@ function createReducer<M, L>(structure: Structure<M, L>) {
result = setIn(result, 'active', field)
return result
},
[INITIALIZE](state, { payload, meta: { keepDirty, keepSubmitSucceeded, updateUnregisteredFields } }) {
[INITIALIZE](
state,
{
payload,
meta: { keepDirty, keepSubmitSucceeded, updateUnregisteredFields }
}
) {
const mapData = fromJS(payload)
let result = empty // clean all field state

Expand All @@ -292,9 +305,9 @@ function createReducer<M, L>(structure: Structure<M, L>) {
}

// persist old errors, they will get recalculated if the new form values are different from the old values
const error = getIn(state, 'error')
if (error) {
result = setIn(result, 'error', error)
const syncFormWideError = getIn(state, 'syncFormWideError')
if (syncFormWideError) {
result = setIn(result, 'syncFormWideError', syncFormWideError)
}
const syncErrors = getIn(state, 'syncErrors')
if (syncErrors) {
Expand Down Expand Up @@ -345,7 +358,9 @@ function createReducer<M, L>(structure: Structure<M, L>) {
}

if (!updateUnregisteredFields) {
forEach(keys(registeredFields), name => overwritePristineValue(name))
forEach(keys(registeredFields), name =>
overwritePristineValue(name)
)
}

forEach(keys(newInitialValues), name => {
Expand Down Expand Up @@ -411,13 +426,13 @@ function createReducer<M, L>(structure: Structure<M, L>) {
if (payload && Object.keys(payload).length) {
const { _error, ...fieldErrors } = payload
if (_error) {
result = setIn(result, 'error', _error)
result = setIn(result, 'asyncFormWideError', _error)
}
if (Object.keys(fieldErrors).length) {
result = setIn(result, 'asyncErrors', fromJS(fieldErrors))
}
} else {
result = deleteIn(result, 'error')
result = deleteIn(result, 'asyncFormWideError')
}
return result
},
Expand All @@ -426,23 +441,32 @@ function createReducer<M, L>(structure: Structure<M, L>) {
result = deleteIn(result, 'submitting')
result = deleteIn(result, 'submitFailed')
result = deleteIn(result, 'submitSucceeded')

if (payload && Object.keys(payload).length) {
const { _error, ...fieldErrors } = payload
const isFieldErrorsPresent = !!Object.keys(fieldErrors).length
if (_error) {
result = setIn(result, 'error', _error)
result = setIn(result, 'submitFormWideError', _error)
result = setIn(result, `submitErrorsUpToDate`, true)
} else {
result = deleteIn(result, 'error')
result = deleteIn(result, 'submitFormWideError')
}
if (Object.keys(fieldErrors).length) {
if (isFieldErrorsPresent) {
result = setIn(result, 'submitErrors', fromJS(fieldErrors))
result = setIn(result, `submitErrorsUpToDate`, true)
} else {
result = deleteIn(result, 'submitErrors')
}
if (!_error && !isFieldErrorsPresent) {
result = deleteIn(result, `submitErrorsUpToDate`)
}
result = setIn(result, `submitErrorsUpToDate`, true)
result = setIn(result, 'submitFailed', true)
} else {
result = setIn(result, 'submitSucceeded', true)
result = deleteIn(result, 'error')
result = deleteIn(result, 'submitFormWideError')
result = deleteIn(result, 'submitErrors')
result = deleteIn(result, `submitErrorsUpToDate`)
}
return result
},
Expand Down Expand Up @@ -530,11 +554,9 @@ function createReducer<M, L>(structure: Structure<M, L>) {
[UPDATE_SYNC_ERRORS](state, { payload: { syncErrors, error } }) {
let result = state
if (error) {
result = setIn(result, 'error', error)
result = setIn(result, 'syncError', true)
result = setIn(result, 'syncFormWideError', error)
} else {
result = deleteIn(result, 'error')
result = deleteIn(result, 'syncError')
result = deleteIn(result, 'syncFormWideError')
}
if (Object.keys(syncErrors).length) {
result = setIn(result, 'syncErrors', syncErrors)
Expand All @@ -546,9 +568,9 @@ function createReducer<M, L>(structure: Structure<M, L>) {
[UPDATE_SYNC_WARNINGS](state, { payload: { syncWarnings, warning } }) {
let result = state
if (warning) {
result = setIn(result, 'warning', warning)
result = setIn(result, 'warningSync', warning)
} else {
result = deleteIn(result, 'warning')
result = deleteIn(result, 'warningSync')
}
if (Object.keys(syncWarnings).length) {
result = setIn(result, 'syncWarnings', syncWarnings)
Expand Down
30 changes: 23 additions & 7 deletions src/createReduxForm.js
Original file line number Diff line number Diff line change
Expand Up @@ -218,6 +218,10 @@ export type Props = {
dispatch: Dispatch<*>,
enableReinitialize: boolean,
error?: any,
syncFormWideError?: any,
asyncFormWideError?: any,
submitFormWideError?: any,
submitErrorsUpToDate: boolean,
focus: FocusAction,
form: string,
getFormState: GetFormState,
Expand Down Expand Up @@ -354,21 +358,22 @@ const createReduxForm = (structure: Structure<*, *>) => {

updateSyncErrorsIfNeeded(
nextSyncErrors: ?Object,
nextError: ?any,
nextSyncError: ?any,
lastSyncErrors: ?Object
) {
const { error, updateSyncErrors } = this.props
const { syncFormWideError, updateSyncErrors } = this.props
const noErrors =
(!lastSyncErrors || !Object.keys(lastSyncErrors).length) && !error
(!lastSyncErrors || !Object.keys(lastSyncErrors).length) &&
!syncFormWideError
const nextNoErrors =
(!nextSyncErrors || !Object.keys(nextSyncErrors).length) &&
!nextError
!nextSyncError
if (
!(noErrors && nextNoErrors) &&
(!plain.deepEqual(lastSyncErrors, nextSyncErrors) ||
!plain.deepEqual(error, nextError))
!plain.deepEqual(syncFormWideError, nextSyncError))
) {
updateSyncErrors(nextSyncErrors, nextError)
updateSyncErrors(nextSyncErrors, nextSyncError)
}
}

Expand All @@ -387,6 +392,7 @@ const createReduxForm = (structure: Structure<*, *>) => {
}
}

// Runs synchronous validators
validateIfNeeded(nextProps: ?Props) {
const { shouldValidate, shouldError, validate, values } = this.props
const fieldLevelValidate = this.generateValidator()
Expand Down Expand Up @@ -946,6 +952,7 @@ const createReduxForm = (structure: Structure<*, *>) => {
const pristine = shouldResetValues || deepEqual(initial, values)
const asyncErrors = getIn(formState, 'asyncErrors')
const syncErrors = getIn(formState, 'syncErrors') || {}
const submitErrors = getIn(formState, 'submitErrors')
const syncWarnings = getIn(formState, 'syncWarnings') || {}
const registeredFields = getIn(formState, 'registeredFields')
const valid = isValid(form, getFormState, false)(state)
Expand All @@ -954,22 +961,31 @@ const createReduxForm = (structure: Structure<*, *>) => {
const submitting = !!getIn(formState, 'submitting')
const submitFailed = !!getIn(formState, 'submitFailed')
const submitSucceeded = !!getIn(formState, 'submitSucceeded')
const error = getIn(formState, 'error')
const syncFormWideError = getIn(formState, 'syncFormWideError')
const submitFormWideError = getIn(formState, 'submitFormWideError')
const error =
syncFormWideError ||
getIn(formState, 'asyncFormWideError') ||
getIn(formState, 'submitFormWideError')
const warning = getIn(formState, 'warning')
const triggerSubmit = getIn(formState, 'triggerSubmit')

return {
anyTouched,
asyncErrors,
asyncValidating: getIn(formState, 'asyncValidating') || false,
dirty: !pristine,
error,
syncFormWideError,
initialized,
invalid: !valid,
pristine,
registeredFields,
submitting,
submitErrors,
submitFailed,
submitSucceeded,
submitFormWideError,
syncErrors,
syncWarnings,
triggerSubmit,
Expand Down
5 changes: 2 additions & 3 deletions src/handleSubmit.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,13 +26,12 @@ const handleSubmit = (
syncErrors,
asyncErrors,
touch,
values,
persistentSubmitErrors
values
} = props

touch(...fields) // mark all fields as touched

if (valid || persistentSubmitErrors) {
if (valid) {
const doSubmit = () => {
let result
try {
Expand Down
8 changes: 7 additions & 1 deletion src/selectors/getFormError.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,13 @@ const createGetFormError = ({ getIn }: Structure<*, *>) => (
): GetFormErrorInterface => (state: any) => {
const nonNullGetFormState: GetFormState =
getFormState || (state => getIn(state, 'form'))
return getIn(nonNullGetFormState(state), `${form}.error`)
const formState = nonNullGetFormState(state)

return (
getIn(formState, `${form}.syncFormWideError`) ||
getIn(formState, `${form}.asyncFormWideError`) ||
getIn(formState, `${form}.submitFormWideError`)
)
}

export default createGetFormError
24 changes: 15 additions & 9 deletions src/selectors/isValid.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,19 +14,25 @@ const createIsValid = (structure: Structure<*, *>) => {
const nonNullGetFormState: GetFormState =
getFormState || (state => getIn(state, 'form'))
const formState = nonNullGetFormState(state)
const syncError = getIn(formState, `${form}.syncError`)
if (syncError) {
const submitErrorsToBeRespected = !ignoreSubmitErrors
? true
: !!getIn(formState, `${form}.submitErrorsUpToDate`)

const syncFormWideError = getIn(formState, `${form}.syncFormWideError`)
const asyncFormWideError = getIn(formState, `${form}.asyncFormWideError`)
const submitFormWideError = getIn(formState, `${form}.submitFormWideError`)

if (
syncFormWideError ||
asyncFormWideError ||
(submitFormWideError && submitErrorsToBeRespected)
) {
return false
}
if (!ignoreSubmitErrors) {
const error = getIn(formState, `${form}.error`)
if (error) {
return false
}
}

const syncErrors = getIn(formState, `${form}.syncErrors`)
const asyncErrors = getIn(formState, `${form}.asyncErrors`)
const submitErrors = ignoreSubmitErrors
const submitErrors = !submitErrorsToBeRespected
? undefined
: getIn(formState, `${form}.submitErrors`)
if (!syncErrors && !asyncErrors && !submitErrors) {
Expand Down

0 comments on commit ac752d3

Please sign in to comment.