Home > database >  How to access input value inside `transformErrors`
How to access input value inside `transformErrors`

Time:09-22

When mapping errors inside transformErrors callback, I need to know the actual value of the input in question.

I need this to create a system for composing multiple existing formats into new composite formats. I want to match the input value against each of the "basic" formats and display the error for the one that fails. The allOf method of composing formats unfortunately doesn't work for me, for reasons very specific to my project.

I tried injecting the form data into my tranformErrors callback via currying and reading the data directly:

import _ from 'lodash'
import Form from '@rjsf/core'

const makeTransformErrors = formData => errors => {
  errors.forEach(error => {
    if (error.name === 'format') {
      const value = _.get(formData, error.property)
      // ...
    }
  })
}

const WrapedForm = (formData, ...rest) => {
  const transformErrors = makeTransformErrors(formData)
  return (
    <Form 
      transformErrors={transformErrors} 
      formData={formData}
      {...rest} 
    />
  )
}

but this way value lags one keystroke behind the actual state of the form, which is what I was expecting. Unfortunately this doesn't work even when I don't pass formData into makeTransformErrors directly, but instead I pass in an object containing formData and directly mutate it imeditately inside Forms onChange, which I was expecting to work.

What are other possible ways of accessing the field's value? Maybe it could be possible to configure (or patch) ajv validator to attatch the value to validation error's params?

CodePudding user response:

Not sure exactly what kind of error validation you are trying todo, but have you tried using validate?

It can be passed as such :

 <Form .... validate={validate} />

where validate is a function that takes as arguments formData and errors.

See documentation here

CodePudding user response:

Ok, I found a way of achieving what I want, but it's so hacky I don't think I want to use it. I can get the up-to-date value when combining the above mentioned prop mutation trick with using a getter for the message, postponing the evaluation until the message is actually read, which happens to be enough:

import _ from 'lodash'
import Form from '@rjsf/core'

const makeTransformErrors = formDataRef => errors => {
  return errors.map(error => {
    if (error.name !== 'format') return error
      
    return {
      ...error,
      get message() {
        const value = _.get(propPath, formDataRef.current) // WORKS! But at what cost...
      }
    }
  })
}

const WrapedForm = (formData, onChange, ...rest) => {
  const formDataRef = React.useRef(formData)

  const transformErrors = makeTransformErrors(formDataRef)

  handleChange = (params) => {
    formDataRef.current = params.formData
    onChange(params)
  }

  return (
    <Form 
      transformErrors={transformErrors} 
      onChange={handleChange}
      formData={formData}
      {...rest} 
    />
  )
}
  • Related