Skip to content

[Android] Typing becomes laggy with react-hook-form #104

@vfomkin

Description

@vfomkin

When using MaskedTextInput in a form controlled by react-hook-form, the input becomes noticeably slow and laggy when multiple instances (e.g., 15) are rendered on the same screen. Some characters are even skipped when typing fast.
This issue does not occur when using MaskedTextInput as an uncontrolled component or controlled via local useState. This suggests the problem might be related to how the component interacts with react-hook-form and React re-renders.
Possibly related to: #82

export const FormMaskedField = ({ name }: { name: string }) => {
  const { control } = useFormContext();
  const { field } = useController({
    name,
    control,
  });
  return (
    <MaskedTextInput
      onChangeText={field.onChange}
      ref={field.ref}
      value={field.value}
      mask="[__________________________________________________________________]"
      style={{
        borderRadius: 12,
        borderWidth: 1,
        borderColor: '#000',
        backgroundColor: '#fff',
        color: '#000',
        padding: 8,
      }}
    />
  );
};
export const TestForm = () => {
  const methods = useForm();
  const { watch } = methods;
  const values = watch();
  return (
    <FormProvider {...methods}>
      <View style={{ gap: 8 }}>
        {[...Array(15)].map((_, index) => (
          <View key={index}>
            <FormMaskedField name={'test' + index} />
            <Text>
              testValue{index} - {values['test' + index]}
            </Text>
          </View>
        ))}
      </View>
    </FormProvider>
  );
};

Typing becomes laggy and unresponsive when many masked inputs are controlled via react-hook-form.

2025-04-07.18.07.13.mov

When switching to a version that uses local state (without react-hook-form), performance is fine:

export const ControlledMaskedField = ({ onChangeText, value }: { value: string; onChangeText: (value: string) => void }) => {
  return (
    <MaskedTextInput
      value={value}
      onChangeText={onChangeText}
      mask="[__________________________________________________________________]"
      style={{
        borderRadius: 12,
        borderWidth: 1,
        borderColor: '#000',
        backgroundColor: '#fff',
        color: '#000',
        padding: 8,
      }}
    />
  );
};
export const TestStateForm = () => {
  const [values, setValues] = useState<Record<string, string>>({});
  return (
    <View style={{ gap: 8 }}>
      {[...Array(15)].map((_, index) => (
        <View key={index}>
          <ControlledMaskedField
            value={values['test' + index] || ''}
            onChangeText={val => setValues(prev => ({ ...prev, ['test' + index]: val }))}
          />
          <Text>
            testValue{index} - {values['test' + index]}
          </Text>
        </View>
      ))}
    </View>
  );
};

Expected behavior
Input should remain smooth and responsive even with many MaskedTextInput components using react-hook-form.

  • Desktop OS: [MacOS 15.2]
  • Android Device: [Samsung S22] API v34 / Android14
  • RN version: 0.78
  • RN architecture: [old]
  • Library version: [1.3.5]

Metadata

Metadata

Assignees

Labels

bugSomething isn't working

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions