react-final-form-listeners icon indicating copy to clipboard operation
react-final-form-listeners copied to clipboard

Infinity loop if the value is NaN

Open eugenekgn opened this issue 6 years ago • 1 comments

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

eugenekgn avatar Jun 27 '19 19:06 eugenekgn

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);
  });

leighmetzroth avatar Dec 22 '22 00:12 leighmetzroth