简体   繁体   中英

Using Formik and wrapping Material TextField causing blur on keypress

I'm not sure what I changed to make my custom TextField s to start behaving this way but I'm wrapping Material-UI TextField s to use Formik validation. I've included a full code sandbox to fork and play with.

Currently, when I type (or click an up/down arrow in the case of a numeric field) the field "blurs" and I have to refocus every keypress to continue typing. The numeric field causes the number to drop in value instead of increase.

Here is my custom TextField wrapper:

import React from "react";
import { FieldAttributes, useField } from "formik";
import {
  InputBaseComponentProps,
  TextField as MuiTextField
} from "@material-ui/core";

interface TextFieldProps {
  label: string;
  inline?: boolean;
  inputProps?: InputBaseComponentProps;
}

const TextField: React.FC<FieldAttributes<TextFieldProps>> = ({
  inline = false,
  ...props
}) => {
  const { type, label, placeholder, inputProps } = props;
  const [field, meta] = useField<TextFieldProps>(props);
  const errorText = meta.error && meta.touched ? meta.error : "";

  const Field = () => (
    <MuiTextField
      {...field}
      label={label}
      variant="outlined"
      margin="dense"
      type={type}
      placeholder={placeholder ? placeholder : label}
      helperText={errorText}
      error={!!errorText}
      inputProps={inputProps}
    />
  );

  return inline ? (
    <Field />
  ) : (
    <div>
      <Field />
    </div>
  );
};

export default TextField;

Below is the code sandbox in case my sample code has nothing to do with what I'm doing wrong:

https://codesandbox.io/s/eager-black-jw717

I think you are hitting the recreation of MuiTextField every time you enter text or focus on field.

React will run all the codes again when re-rendering in functional component, so the Field() will create MuiTextField again.

To solve it, you can separate the Field and TextField into 2 components.

const Field: React.FC<FieldAttributes<TextFieldProps>> = (props) => {
  const { type, label, placeholder, inputProps } = props;
  const [field, meta] = useField<TextFieldProps>(props);
  const errorText = meta.error && meta.touched ? meta.error : "";

  return (
    <MuiTextField
      {...field}
      label={label}
      variant="outlined"
      margin="dense"
      type={type}
      placeholder={placeholder ? placeholder : label}
      helperText={errorText}
      error={!!errorText}
      inputProps={inputProps}
    />
  );
};

const TextField: React.FC<FieldAttributes<TextFieldProps>> = ({
  inline = false,
  ...props
}) => {
  return inline ? (
    <Field {...props} />
  ) : (
    <div>
      <Field {...props} />
    </div>
  );
};

Here is the codesandbox:

https://codesandbox.io/s/interesting-rain-8tl14?file=/src/components/TextField.tsx:839-848

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM