final-form / react-final-form-listeners

A collection of components to listen to 🏁 React Final Form fields
MIT License
94 stars 20 forks source link

OnChange function is called on every render instead of user interaction. #7

Open pandey-sid opened 5 years ago

pandey-sid commented 5 years ago

Are you submitting a bug report or a feature request?

bug report

What is the current behavior?

I’m using this inside a field array, I basically want to reset an input text field on change of a dropdown/select field item. It works fine as expected. But when I delete that row, the field-array template is re-rendered that causes the onChange of the dropdown in each row to execute again that resets the other selections made by the user.

What is the expected behaviour?

The expected behaviour is that the onChange handler should only be called when a user performs a change to the input/select. It shouldn't be called by re-render of FieldArray.

I've followed the example that is mentioned here: It says that "It’s important to notice that the function given to OnChange will only be called when the value changes, not on every render."

Sandbox Link

What's your environment?

"react": "^16.3.2", "react-apollo": "^2.3.1", "react-beautiful-dnd": "^9.0.2", "react-dom": "^16.3.2", "react-final-form": "^3.6.2", "react-final-form-listeners": "^1.0.1", "react-final-form-arrays": "^1.0.6" Mac - Chrome Browser Version 70.0.3538.110 (Official Build) (64-bit)

HawiCaesar commented 5 years ago

Sandbox link @pandey-sid ?

JackHowa commented 5 years ago

Having this issue too

JackHowa commented 5 years ago

This was helpful fix for me, using the previous param:

import { Field } from 'react-final-form';
import { OnChange } from 'react-final-form-listeners';

// based off of library author https://medium.com/@erikras/declarative-form-rules-c5949ea97366
const WhenFieldChanges = ({ field, set, to }) => (
  <Field name={set} subscription={{}}>
    {({ input: { onChange } }) => (
      <OnChange name={field}>
        {(value, previous) => {
          // prevent on render issue changing the field
          if (previous !== '') {
            onChange(to);
          }
        }}
      </OnChange>
    )}
  </Field>
);

export default WhenFieldChanges;
Hyokune commented 4 years ago

This was helpful fix for me, using the previous param:

import { Field } from 'react-final-form';
import { OnChange } from 'react-final-form-listeners';

// based off of library author https://medium.com/@erikras/declarative-form-rules-c5949ea97366
const WhenFieldChanges = ({ field, set, to }) => (
  <Field name={set} subscription={{}}>
    {({ input: { onChange } }) => (
      <OnChange name={field}>
        {(value, previous) => {
          // prevent on render issue changing the field
          if (previous !== '') {
            onChange(to);
          }
        }}
      </OnChange>
    )}
  </Field>
);

export default WhenFieldChanges;

How would you do this if you want the field change to display a FieldArray (Push one to a FieldArray since the componentDidMount() has issues with initialising one item in the array)