DEV Community

André Ovalle
André Ovalle

Posted on • Edited on

Expandiendo el hook useFormik con objetos anidados en Typescript

Cuando se esta desarrollando algún proyecto utilizando la librería se consulta en la documentación de esa librería con el objetivo de saber como se puede utilizar. Formik es una de las librerías más usadas para poder manejar los formularios en proyectos web. Ademas, se encarga de manejar las validaciones y el evento submit. Esta libería también cuenta para manejo de formularios, con inputs ya integrados con Formik y hooks en caso que se no se quiera usar dichos inputs.

En la documentación con esa librería se cuentan con ejemplos para varíos casos usando sus inputs personalizados. Uno de ellos son objetos anidados demostrando soporte para este tipo de objetos. Si bien se evidencia el soporte de objetos anidados en caso de querer usar los hooks con los que cuenta la librería, no existen ejemplos. Por lo que aquí daremos apoyo a la duda de como se pueden integrar objetos anidados usando solo los hooks de la libería.

Todo el código utilizado para este tutorial lo podrás entrar aquí: useFormik.

Para quien quiera una demo funcional: useFormik demo

Valores Iniciales

Para empezar aclarando que en este ejemplo utilizaremos el hook useFormik pero, el ejemplo se puede aplicar con cualquier hook de la libería. Primero declaremos el objeto inicial con el que estaremos trabajando junto a su tipado.

interface  UserInfo  {
    personal:  {
        name:  string;
        lastName:  string;
        age:  number;
    };
    location:  {
        address:  string;
        country:  string;
    };
}

const  initialValues:  UserInfo  =  {
    personal:  {
        name:  "",
        lastName:  "",
        age:  0,
    },
    location:  {
        address:  "",
        country:  "",
    },
};
Enter fullscreen mode Exit fullscreen mode

También inicializamos los validadores que utilizaremos para nuestro formulario. Para efectos de este ejemplo utilizaremos la libería de validadores Yup para facilitar validaciones.

const  validationSchema  =  yup.object().shape({
    personal:  yup.object().shape({
        name:  yup.string().required("Name is required"),
        lastName:  yup.string().required("Last name is required"),
        age:  yup
        .number()
        .required("Age is required")
        .min(1,  "You should have at least 1 year"),
    }),
    location:  yup.object().shape({
        address:  yup.string().required("Address is required"),
        country:  yup.string().required("Country is required"),
    }),
});
Enter fullscreen mode Exit fullscreen mode

Formik

Inicializamos el formik que vamos a utilizar para manejar nuestro formulario.

const  formik  =  useFormik<UserInfo>({
    initialValues,
    validationSchema,
    onSubmit:  (values, { resetForm })  =>  {
        console.log("values: ",  values);
        toast.current?.show({
            severity:  "success",
            summary:  "Form submitted",
            detail:  "The form was submitted",
        });
        resetForm();
    },
});
Enter fullscreen mode Exit fullscreen mode

Con esto procederemos a explicar los inputs donde encontraremos la clave para utilizar objetos anidados

Inputs

Para evitar repetir código crearemos unos inputs especiales para que puedan ser útilizado en nuestro formulario de ejemplo. Aqui expongo uno de los tres tipos de input que crearemos para este formulario. Los otros dos los pueden encontrar en la demo o en el código subido al repositorio.

<InputText
    id={name}
    name={name}
    value={get(formik.values,  name)}
    onChange={formik.handleChange}
    onBlur={formik.handleBlur}
    className={classNames({  "p-invalid":  isInvalid(name,  formik)  })}
/>
Enter fullscreen mode Exit fullscreen mode

En esta clase de input podemos ver que la forma de detectar los cambios en el input es la misma forma que con los campos no anidados. Para obtener el valor solo basta con primero acceder al objeto anidado y luego al campo especifico. Formik para poder manejar los campos de objetos anidados y poder cambiarlos utiliza la siguiente sintaxis: "ob1.ob2.....objn.campo". Para poder acceder a su información solo basta con utilizar una función que permita con solo dar el objeto formik.values y el campo como la sintaxis descrita arriba traer el valor en cuestión. En este caso utilizamos la función get de la libería lodash para poder cumplir con dicha función.

Resultado

Luego de ver las partes que componen el formulario tendremos como resultado algo similar:

function  App()  {
    const  toast  =  useRef<Toast>(null);

    const  formik  =  useFormik<UserInfo>({
        initialValues,
        validationSchema,
        onSubmit:  (values, { resetForm })  =>  {
            console.log("values: ",  values);
            toast.current?.show({
                severity:  "success",
                summary:  "Form submitted",
                detail:  "The form was submitted",
            });
            resetForm();
        },
    });

    return  (
        <div  className="App">
        <Toast  ref={toast}  />
        <form
            className="w-full h-full flex flex-column align-items-center"
            onSubmit={formik.handleSubmit}
        >
            <h1>useFormik with nested objects</h1>
            <h2>Personal Info</h2>
            <div  className="flex flex-column gap-4">
                <MInputText  
                    name="personal.name"  
                    label="Name"  
                    formik={formik}  
                />
                <MInputText
                    name="personal.lastName"
                    label="Last name"
                    formik={formik}
                />
                <MInputNumber  
                    name="personal.age" 
                    label="Age" 
                    formik={formik}
                />
            </div>
            <h2>Address Info</h2>
            <div  className="flex flex-column gap-4">
            <MInputText  
                name="location.address"  
                label="Address"  
                formik={formik}  
            />
            <MDropdown
                name="location.country"
                label="Country"
                formik={formik}
                options={countries}
            />
            </div>
            <Button  
                label="Send Form"  
                type="submit"  
                className="mt-4"
            />
        </form>
        </div>
    );
}
Enter fullscreen mode Exit fullscreen mode

Por lo que usar objetos anidados con los hooks de useFormik no es complicado. Solo es de recordar que para editar los campos se utiliza la notación obj.campo y utilizar una función auxiliar para obtener los valores.

Bibliografía

Formik: https://formik.org/docs/overview

Top comments (0)