Skip to content

When instantiating a Form that uses a FieldArray , in both cases ~init=None && ~init=Some([]), nested elements inside the FieldArray do not update as expected. #3

@KateChanthakaew

Description

@KateChanthakaew

Description

Calling Form.use(. ~init=None, ...) or with Form.use(. ~init=Some([]), ...), notice the FieldArray elements are not updating as expected.

Reproduction

We create a FieldArray named LoginArray to contain the field Login as the nested elements. Our example below is driven from the FieldArray example found in Everything.res.

Note: The bug occurs when a FieldArray is nested inside a FieldProduct, and also when a FieldProduct is the element inside a FieldArray. The issue occurs for filterIdentity and filterGrace type FieldArray, however we're just showing the filterIdentity version with a Form.use(. ~init=Some([]), ...) in our example below.

module Status = {
  @react.component
  let make = (~title=?, ~enum: Store.enum, ~error) => {
    <div className={`status ${enum->Store.enumToA}`}>
      {title->Option.map(x => `${x}: `->React.string)->Option.or(React.null)}
      {`${error->Option.or(enum->Store.enumToPretty)}`->React.string}
    </div>
  }
}

module LoginArray = {
  module Field = FieldArray.Make(
    Login.Field,
    {
      type t = Login.Field.t
      let filter = FieldArray.filterIdentity
    },
  )

  let validate = (out: Field.output) => {
    if out->Array.length < 2 {
      Error("Must choose at least two logins")
    } else {
      Ok()
    }
    ->Promise.return
    ->Promise.delay(~ms=1000)
  }

  let contextDefault: Field.context = {
    validate,
    empty: _ => [],
    element: Login.contextValidate,
  }

  module Input = {
    @react.component
    let make = (~form: Fields.Form.t<Field.t, Field.actions<unit>>) => {
      let forms = form->Field.split

      let handleAdd = e => {
        e->ReactEvent.Mouse.preventDefault
        e->ReactEvent.Mouse.stopPropagation
        form.actions.add(None)
      }
      let handleRemove = (~index, e) => {
        e->ReactEvent.Mouse.preventDefault
        e->ReactEvent.Mouse.stopPropagation
        form.actions.remove(index)
      }
      let handleClear = e => {
        e->ReactEvent.Mouse.preventDefault
        e->ReactEvent.Mouse.stopPropagation
        form.actions.clear()
      }

      let handleReset = e => {
        e->ReactEvent.Mouse.preventDefault
        e->ReactEvent.Mouse.stopPropagation
        form.actions.reset()
      }

      <div>
        {forms
        ->Array.mapi((f, i) => {
          <div className="row" key=`${i->Int.toString}`>
            <div className="column">
              <Login.Input form=f />
            </div>
            <button className="button-clear" onClick={handleRemove(~index=i)}>
              {"✕"->React.string}
            </button>
          </div>
        })
        ->React.array}
        <div className="row">
          <Status
            title="Addresses" enum={form.field->Field.enum} error={form.field->Field.printError}
          />
        </div>
        <div className="row">
          <button className="button-clear column column-20" onClick={handleAdd}>
            {"Add One"->React.string}
          </button>
          <button className="button-clear float-left" onClick={handleReset}>
            {"Reset"->React.string}
          </button>
          <button className="button-clear float-left" onClick={handleClear}>
            {"Clear"->React.string}
          </button>
        </div>
      </div>
    }
  }
}

module Field = LoginArray.Field
module Form = UseField.Make(Field)

@react.component
let make = (~onSubmit) => {
  let form = Form.use(.
    ~context=LoginArray.contextDefault,
    ~init=None,
    ~validateInit=false,
  )

  Js.log2("form.field: ", form.field->Field.show)

  let handleSubmit = React.useMemo1( () => {
    (_) => form.field->Field.output->Option.map(onSubmit)->Option.void
  }, [form.field->Field.output])

	<div className="container">
		<form onSubmit={handleSubmit}>
			<h2>{"Addresses"->React.string}</h2>
			<LoginArray.Input form />
			<button type_="submit"> {"Sign In"->React.string} </button>
		</form>
	</div>
}

  • 2.1 when supplied with ~init=None, we show there is a valid onChange with a target[value] but the field does not receive the changed values.
array_None.mov
  • 2.2 Similar to 2.1, If we init with ~init=Some([ ]), updating the FieldArray element's fields does not propagate the changes to the FieldArray parent.
array_some-empty-array.mov

Expected Behavior

  • Expected form.field and its FieldArray elements to store their updated values on a field.actions.set(value).

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions