How to render Formik Field as textarea + styled-components?
Asked Answered
D

2

8

I am working with styled-components and Formik. Everything is working well except textareas or selects etc. Styled-components and Formik have got same attribute as and when I want to connect this I am getting not expected results.

<StyledTextArea as={Field} placeholder="" name="topic" id="topic"></StyledTextArea>

Using Formik we need to pass an attribute as for Field element as well. It should looks like this:

<Field as="textarea" id="topic" name="topic"></Field>

I fixed this with writing this:

const StyledTextareaField = (props) => (
    <Field {...props} as="textarea" id="description" name="description" children={props.children}></Field>
  );

and this:

<StyledTextArea
              as={StyledTextareaField}
              placeholder="Wpisz opis spotkania"
              id="description"
              name="description"
            ></StyledTextArea>

But my problem is that when I start typing after one letter I am losing focus from textarea and I must click once again to fill next letter etc.

Discophile answered 18/5, 2020 at 12:47 Comment(2)
Are you using it inside a map?Hardtop
Nope, each Field is a separated html elementDiscophile
D
6

The problem with losing focus after typing just one character is because of the component is newly created and mounted in DOM after each render.

You can prevent it by wrapping you component with React.memo().

A formik field component can be written as follows:

import {Field} from "formik";
import React from "react";

function MyFormikTextareaField({fieldName}){
  return (
    <Field name={fieldName}>
      {({field, form, meta}) => {
        return (
            <MyStyledTextareaComponent
              value={field.value}
              onChange={field.onChange}
            />
        );
      }}
    </Field>
  )
}

If you prefer to use React hooks, then you can write something like:

function MyFormikTextareaField({fieldName}) {
  const [field, meta, helpers] = useField(fieldName);

  return (
    <MyStyledTextareaComponent
      value={meta.value}
      onChange={field.onChange}
    />
  );
}
Deviltry answered 18/5, 2020 at 13:0 Comment(0)
M
0
# use  <textarea/> instead of <input/>

        <input
                          placeholder='description'
                          {...formik.getFieldProps('description')}
                          name='description'
                          className={clsx(
                            'form-control form-control-solid mb-3 mb-lg-0',
                            {'is-invalid': formik.touched.description && formik.errors.description},
                            {
                              'is-valid': formik.touched.description && !formik.errors.description,
                            }
                          )}
                          autoComplete='off'
                          disabled={formik.isSubmitting || loading}
                        />
                        
                        
                        ----------------
                        

     <textarea
                          placeholder='description'
                          {...formik.getFieldProps('description')}
                          name='description'
                          className={clsx(
                            'form-control form-control-solid mb-3 mb-lg-0',
                            {'is-invalid': formik.touched.description && formik.errors.description},
                            {
                              'is-valid': formik.touched.description && !formik.errors.description,
                            }
                          )}
                          autoComplete='off'
                          disabled={formik.isSubmitting || loading}
                        />

`

Moorings answered 9/4, 2023 at 6:7 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.