1

I have a form, and this form was getting too complex for one component.

So I made a subsection for a part of the form which has multiple dynamic inputs and gives a single output and validates itself. It doesn't have a submit button, on every change it just passes back the computed result and if it is validated successfully or not.

    // Contains multiple input fields, passes its result when 
    // filled in properly and errors if not filled in properly 
    // so I can disable the submit button.
    // Also contains a clear method internally.
    <AddItemPresetsInput
      onChange={handlePresetItemsChange}
      errorsChanged={handlePresetErrorsChange}
    ></AddItemPresetsInput>

I want the parent, after being submitted, to clear this subform and reset it. What I'd love to do is call the child's clear() method. But this appears to be bad practice from this post:

Call child method from parent

So I see a few options:

  • Use Refs to call child's clear method - Not recommended in React's docs: Avoid using refs for anything that can be done declaratively.
  • Lift the state of the subform to the parent which would allow me to change props to clear the form. But this goes against my initial goal of abstracting this logic to a subcomponent as the child can do everything self contained and it makes the parent complex.
  • Use the key attribute and change the key on submit - this is what I'm doing, it just seems to be hacky.

    <AddItemPresetsInput
      onChange={handlePresetItemsChange}
      errorsChanged={handlePresetErrorsChange}
      key={presetItemsKey}
    ></AddItemPresetsInput>
    

Am I missing an option? It seems option 2 is the way to go with how the React Docs recommend doing it.

Diesel
  • 5,099
  • 7
  • 43
  • 81
  • It's complicated to understand what you really want, can you describe with a simple image? – Tolotra Raharison Nov 29 '19 at 16:06
  • 1
    I actually came across this problem recently. I tried many things like `Event Emitters` or a subscription functionality (like with web sockets for example). But lifting the state up to the parent component or maybe even put in a global state/context seemed to be the best solution. I ended up putting my whole logic in a context, this way the child components are more flexible and easier to extend. But I also want a better solution which is in the mind of reacts philosophy. – oemera Nov 29 '19 at 16:08
  • 1
    You can checkout this discussion: https://github.com/facebook/react/issues/6646 At least you can see how others share the same pain :') – oemera Nov 29 '19 at 16:17

1 Answers1

0

If the parent is responsible for submitting the form, it makes sense that the properties of the form (child component) are passed on from the parent, in which case resetting the properties at parent level will automatically propagate to the child.

What you are asking is a bit contradictory:

  • Encapsulate properties at the child so the parent cannot touch them
  • Clear the properties from the parent on submit.

This doesn't make a lot of sense to me.

However you can achieve desired result with the redux pattern if you want to, by storing state in an application level store. This way you would dispatch an action to clear the form state from the parent, and have the child component receive the props from the store.

html_programmer
  • 18,126
  • 18
  • 85
  • 158
  • 1
    I don't want to encapsulate it so the parent cannot touch it, I just want to make all the complex inputs and logic to validate in its own component. That being said, I think lifting state up makes sense and changing it so that the properties are simple to the parent and the leg-work is done by the child is the answer (if possible). – Diesel Nov 29 '19 at 16:44
  • Sounds like a viable idea. – html_programmer Nov 29 '19 at 16:46