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

Infinity loop if the value is NaN #11

Open eugenekgn opened 5 years ago

eugenekgn commented 5 years ago

It seems like there's an infinite loop that <onChange name={value}/> throws if the watched value happens to be NaN

leighmetzroth commented 1 year ago

I've also run into this and narrowed it down to the fact that NaN !== NaN. If you use the lodash function isEqual for the equality comparison then it should work a lot more reliably.

e.g.

    if (!isEqual(value, previous)) {
      this.setState({ previous: value })
      children(value, previous)
    }

Below is a failing test that confirms the issue (it fails due to "Maximum update depth exceeded.").

  it('should only invoke the listener once when a number field is cleared', async () => {
    const spy = jest.fn();
    render(
      <Form onSubmit={() => {}} initialValues={{ value: 1 }}>
        {() => (
          <form>
            <Field<number> name="value">
              {({ input: { onChange, value, ...inputRest } }) => (
                <input
                  {...inputRest}
                  value={value}
                  type="number"
                  onChange={e => onChange(e.target.valueAsNumber)}
                />
              )}
            </Field>
            <OnChange name="value">{spy}</OnChange>
          </form>
        )}
      </Form>
    );

    expect(spy).not.toHaveBeenCalled();

    await userEvent.clear(getByRole('spinbutton'));

    expect(spy).toHaveBeenCalledTimes(1);
    expect(spy).toHaveBeenCalledWith(NaN, 1);
  });