rescriptbr / reform

📋 Reasonably making forms sound good
https://rescript-reform.netlify.app/
MIT License
354 stars 41 forks source link

feat: add handleChangeWithCallback function #160

Closed Qziem closed 4 years ago

Qziem commented 4 years ago

Some cases of usage requires to have current value while updating. I added handleChange With Callback function because of that.

fakenickels commented 4 years ago

Oh this is nice, it's part of some ideas I was having recently to bring on the handling closer to the fields themselves.

fakenickels commented 4 years ago

Do you have any snippets where this is going to be useful for you? I would like to add to the docs

Qziem commented 4 years ago

@fakenickels My case its quite complicated. Below simplified use in my case (I'm not sure is this case is readable and good for docs)

open BsReform;

// In my case actualy this is no record but more complex array, but for simplicity i used record here
type complexField = {
  subField1: string,
  subField2: string,
};

module StateLenses = [%lenses
  type state = {
    field1: string,
    complexField,
  }
];

module Form = ReForm.Make(StateLenses);

let initialState: StateLenses.state = {
  field1: "",
  complexField: {
    subField1: "",
    subField2: "",
  },
};

module Member = {
  [@react.component]
  let make = () => {
    let {handleChangeWithCallback}: Form.api = Form.useFormContext()->Belt.Option.getExn;

    React.useEffect0(() => {
      open Js.Promise;
      someRequest
      |> then_(response =>
           handleChangeWithCallback(StateLenses.ComplexField, complexField =>
             response == "something"
               ? {...complexField, subField1: response} : {...complexField, subField2: response}
           )
         );
      None;
    });

    <Form.Field
      field=ComplexField
      render={({handleChange, value}) =>
        // ... displaying values
        React.null}
    />;
  };
};

[@react.component]
let make = () => {
  let reform =
    Form.use(
      ~validationStrategy=OnDemand,
      ~schema=Form.Validation.Schema([||]),
      ~onSubmit=
        ({state}) => {
          Js.log2("Saving will be here", state.values);
          None;
        },
      ~initialState,
      (),
    );

  <div>
    <Form.Provider value=reform>
      // two instances of same component
      <Member /> 
      <Member />
    </Form.Provider>
  </div>;
};

Member component send request (two usages are hardcoded but in my case number of this components can be changed dynamiclly by one of form field). When the answer comes, both overwrite the same field in the state. Without handleChangeWithCallback response from the second request would clear the saved state value from the first request.