react-admin icon indicating copy to clipboard operation
react-admin copied to clipboard

Array input issue when removing and reinserting element

Open kriskw1999 opened this issue 3 years ago • 6 comments

Bug

The bug happens when I have inside a SimpleFormIterator a React.FC or a FormDataConsumer. In those cases if I have defaults they are not applied and if there is a record the informations shown does not respect the form state.

To reproduce

To reproduce the bug use this CODESANDBOX Enter into the edit of the only comment present here delete this from the form. Then reinsert it. The form seems filled because you can see the numbers but if you press submit the validation error appears informing you that the form is not filled.

Result of bug: image

Problem found

The screen below is the SimpleFormIterator addField function, in this function if I have a form data consumer or any other React.FC that have not source nor the default value on the SimpleFormIterator level the default returned is {undefined: ""} This causes that react admin renders the array value from the record thinking that the form is filling with the record, showing a wrong value from record and not from the form state. image

Drity workaround to partially solve this issue

type Props<T> = SimpleFormIteratorProps & {
  defaultValue?: { [TKey in keyof T]: T[TKey] }
}

/**
 * This component is used because react admin cannot handle default values for React.FC children of
 * the standard SimpleFormIterator. For those elements the native one takes the default from the record but it
 * does not update the record with like result having the field filled but with an empty form.
 *
 * @param SimpleFormIteratorProps all the props of the SimpleFormIterator
 * @param defaultValue this one is used when a new element is added
 * @return the standard SimpleFormIterator with the ability to add a default value to each element of the array
 */
const KSimpleFormIterator = <T extends any>({
  children,
  source,
  defaultValue,
  ...rest
}: Props<T>) => {
  // this source is automatically passed by the array input
  if (!source) throw new Error('KSimpleFormIterator: source is required')

  // we are going to perform a watch on the the array input values
  const arrayValue = useWatch({ name: source }) as Array<any>

  // we memorize the array input values
  const [value, setValue] = useState(arrayValue)

  // this hook is used to manipulate the ReactAdmin array input form state
  const { append, remove } = useArrayInput({ ...rest })

  console.log('aaa', {
    children: Children.toArray(children),
  })

  // if an element was added
  if (value.length < arrayValue.length) {
    // remove the last added element with wrong default value
    remove(arrayValue.length - 1)
    // set the default value with the correct one appending it like last element of the array
    append(defaultValue)
    // updates the cached value inside the component
    setValue(arrayValue)
  } else if (value.length > arrayValue.length) {
    // updates the cached value inside the component
    setValue(arrayValue)
  }

  return (
    <SimpleFormIterator {...rest} source={source}>
      {children}
    </SimpleFormIterator>
  )
}

export default KSimpleFormIterator

kriskw1999 avatar Sep 19 '22 12:09 kriskw1999

Thank you for reporting this. Your codesandbox doesn't seem to be functional. Can you fix it?

WiXSL avatar Sep 19 '22 12:09 WiXSL

Same happens to me!

@WiXSL codesandbox gives error but if you take its url ( https://gzwqfp.sse.codesandbox.io/#/comments ) you can reproduce it

lsimone avatar Sep 19 '22 12:09 lsimone

@WiXSL try to enter in the link above that is the one of the deployed version where you can reproduce it.

kriskw1999 avatar Sep 19 '22 13:09 kriskw1999

Thanks, seems like a bug. I have to investigate further.

WiXSL avatar Sep 19 '22 13:09 WiXSL

UPDATE: I can reproduce it on stackblitz and codesandbox but not locally. I'll keep investigating

WiXSL avatar Sep 21 '22 19:09 WiXSL

UPDATE: I can reproduce it on stackblitz and codesandbox but not locally. I'll keep investigating

@WiXSL I could reproduce it locally through these steps:

  1. (codesandbox) File > export to ZIP
  2. extract and (p)npm install
  3. (p)npm dev

If I can help to reproduce, please write me!

image

lsimone avatar Sep 22 '22 06:09 lsimone