FORMULARIOS EN REACT
Tags: react, form, webdev, frontend
Published: 2023-08-15 01:11:45

- [FORMIK:]
- [FORMA BÁSICA DE USO:]
- [FORMA DINÁMICA DE USO:]
- [CÓDIGO REFACTORIZADO:]

# FORMIK:

- Librería open-source de componentes de React para construir formularios.
- Ayuda a:
    - **Obtener los valores de entrada y de salida de los estados en un formulario.**
    - **Validaciones y mensajes de error.**
    - **Manejar envío de formularios.**

## Implementación:

Para instalar Formik, asegúrate de tener Node.js y npm (Node Package Manager) instalados en tu computadora. Luego, puedes seguir estos pasos para instalar Formik:

1. Abre una terminal o línea de comandos en tu sistema operativo.
2. Navega al directorio de tu proyecto o crea uno nuevo donde quieras usar Formik.
3. Ejecuta el siguiente comando para instalar Formik a través de npm:
    
    ```
    **npm install formik --save**
    ```
    
    Este comando instalará Formik y lo añadirá como una dependencia en tu archivo **package.json**.
    
4. Después de la instalación, podrás utilizar Formik en tu proyecto importándolo en tus archivos JavaScript o TypeScript:
    
    ```jsx
    **import { Formik, Form, Field, ErrorMessage, useFormik } from 'formik';** //Se importan todo lo neceario para usar "Formik**"**, desde la librería "**formik**"
    ```
    

# FORMA BÁSICA DE USO:

- A una constante declarada arbitrariamente se le asigna el hook personalizado **********************useFormik({}).**********************
- Dicho hook recibe como argumento un objeto con las siguientes propiedades:
    - **initialValues**: Son los valores iniciales, las cuales son colocadas dentro de un objeto, siendo todos los valores iniciales que se tendrán en el formulario. Se deben de definir todos los campos del formulario.
    - **onSubmit**: Función que maneja el evento de entrega de la información del formulario, la cual mediante una función flecha callback o la referencia a una función creada para maneja el evento, va a recibir todos los valores de cada uno de los inputs que se puedan obtener, mediante recibir como argumento un objeto "values" que contiene los valores actuales de todos los campos del formulario, y como segundo argumento el objeto “**formikBag**” del cual se pueden acceder a varias utilidades como métodos mediante la sintaxis de destructuración “****{ }****”, o usar “**formikBag**” y acceder utilizando “**formikBag.nameMetod**”.
    
    ```jsx
    **const formik = useFormik({** //Declaración de constante que será el controlador del formulario, siendo una instancia de "Formik" que almacena el estado y las funciones relacionadas con el formulario con valor asignado de, la función hoot "useFormik", que configura varias opciones importantes mediante un obejto que recibe como argumento y que posee las siguientes propiedades
        **initialValues: {** //Propiedad del objeto, la cual será los valores iniciales de los inputs/controles del fomulario, con valor de un objeto con las siguientes propiedades
            **email: '',** //Propiedad del objeto, que será el valor inicial para el control de "email", con valor asignado de, una cadena vacía 
            **password: ''** //Propiedad del objeto, que será el valor inicial para el control de "password", con valor asignado de, una cadena vacía 
        **},
        onSubmit: (values) => {}** //Propiedad del objeto, que será una función que se ejecutará cuando el formulario sea enviado, con valor asignado de, una función de flecha callback, la cual recibe como argumento un objeto "values" que contiene los valores actuales de todos los campos del formulario.
    **});**
    ```
    
    Lo que retorna la constante **formik**, mediante el uso del hook **useFormik({})**, es un obejto que posee distintos atributos y método necesarios para los formularios.
    
- Una vez creada dicha constante con los datos configurados, mediante un formulario declarado con las etiquetas HTML:
    - En la etiqueta **<form ></form>**, en su propiedad **********************onSubmit={}**********************, se le asigna ************formik.handleSubmit************, haciendo que se llame a ejecutar el valor de la propiedad “**onSubmit**” de la constante “**formik**” la cual es una función para manejar dicho evento, para así pasarle los valores del formulario a la función flecha o la función creada para maneja el evento de dicha propiedad “**********************onSubmit={}**********************”.
        
        Siendo que “**handleSubmit**” es un método interno proporcionado por Formik que se ejecutará cuando se envíe el formulario y manejará los datos del formulario en ese momento.
        
    - En cada uno de los **inputs o elementos del formulario**, en su propiedad “********name********” se le debe de asignar como valor el mismo valor asignado dentro de la propiedad “**initialValues**” correspondiente a su elemento del formulario, para que así se enlacen sus valores.
        - En la propiedad “**********value**********”, dentro de llaves por ser código de JS, desde la constante “**formik**”, se accede a sus valores “**values**” que son los valores iniciales, y se accede al valor correspondiente para el input o elemento
        - En su propiedad **********************onChange={},********************** desde la constante “**formik**”, se ejecuta la función **handleChange** la cual es una función interna de React que maneja el cambio de valor en el campo de entrada y actualiza el estado del componente.
            
            Formik utiliza esta función(**handleChange**) interna de React para escuchar los cambios de los campos del formulario y actualizar automáticamente los valores en su estado interno.
            
    
    ```jsx
    **<form onSubmit={formik.handleSubmit}>** //Etiquta de formulario, la cual posee la propiedad manejadora de ventos del evento de "entregar/enviar" los datos del formulario, con valor asignado de, dentro de llaves por ser código de JS, desde la instancia de Formik "formik", ejecutar su función manejadora de dicho evento la cual hace refencia a la propiedad "onSubmit" de dicha instancia "formik"
        **<input** //Etiqueta de ingreso de datos, la cual posee los siguientes atriutos y propiedades
            **name="email"** //Atributo de "nombre", con valor de dicha cadena de texto la cual es la misma declarada en la propiedad "initialValues" de la instancia de Formik, para enlazar sus valores
            **value={formik.values.email}** //Atributo de "valor", con valo dentro de llaves por ser código de JS, siendo desde la instancia de Formik "formik", acceder a sus "valores" los cuales son los que se encuentran en la propiedad "initialValues" de la instancia de Formik, accediendo a la propiedad "email" de dicha propiedad "initialValues"
            **onChange={formik.handleChange}** //Propiedad manejadora de ventos del evento de "cambio de valor" en éste input, con valor asignado de, dentro de llaves por ser código de JS, desde la instancia de Formik "formik", ejecutar su función manejadora de dicho evento la cual es una función interna de React que maneja el cambio de valor en el campo de entrada y actualiza el estado del componente 
        **/>
    </form>**
    ```
    
    ### EJEMPLO:
    
    ```jsx
    **import { useFormik } from "formik";** //Se importa la función hook para el manejo de formularios, desde, la librería de "formik"
    
    export default function App() { //Se importa como valor por defecto, la declaración de función que será un componente y que ejecuta el siguiente bloque
        **const formData = useFormik({** //Declaración de constante que será el controlador del formulario, siendo una instancia de "Formik" que almacena el estado y las funciones relacionadas con el formulario con valor asignado de, la función hook "useFormik", que configura varias opciones importantes mediante un objeto que recibe como argumento un obejto que posee las siguientes propiedades
            **initialValues: {** //Propiedad del objeto, la cual será los valores iniciales de los inputs/controles del fomulario, con valor de un objeto con las siguientes propiedades
                **email: "",** //Propiedad del objeto, que será el valor inicial para el control de "email", con valor asignado de, una cadena vacía 
                **firstName: "",** //Propiedad del objeto, que será el valor inicial para el control de "firstName", con valor asignado de, una cadena vacía 
                **lastName: ""** //Propiedad del objeto, que será el valor inicial para el control de "lastName", con valor asignado de, una cadena vacía 
            **},
            onSubmit: handleSubmit** //Propiedad del objeto, que será una función que se ejecutará cuando el formulario sea enviado, con valor asignado de, la función declarada para manejar el envío de los datos del formulario
        **});**
    
        **function handleSubmit(values) {** //Declaración de función para manejar el envío de los datos del formulario, la cual recibe como argumento un objeto "values" que contiene los valores actuales de todos los campos del formulario, y que ejecuta el siguiente bloque
            **console.log(values);** //A la consola del navegador, se le aplica el métdo para imprir en la misma, los valores del dicho objeto "values" enviado como argumento
            **formData.resetForm();** //A dicha instancia de "Formik" la cual hace referencia a los valores del formulario, se le aplica el método proporcionado por la misma instancia, para resetear el formulario y todos sus campos
        **}**
    
        return ( //Se retorna una estructura de JSX, el cual será la sección principal del componente a ser renderizado, siendo colocado entre paréntesis
            <div> //Etiqueta contenedora de bloque
                <h1>Basic Form</h1> //Etiqueta de título principal, contiene texto a ser mostrado
                **<form onSubmit={formData.handleSubmit}>** //Etiquta de formulario, la cual posee la propiedad manejadora de ventos del evento de "entregar/enviar" los datos del formulario, con valor asignado de, dentro de llaves por ser código de JS, desde la instancia de Formik "formik", ejecutar su función manejadora de dicho evento la cual hace refencia a la propiedad "onSubmit" de dicha instancia "formik"
                    <div> //Etiqueta contenedora de bloque
                        <label htmlFor="email">Email</label> //Etiqueta para etiquetar elementos de interfaz de usuario, posee el atributo "for" para enlazarla con el elemento correspondiente con valor de una cadena de texto la cual es la misma que el identificador del elemento a ser enlazado, y contiene texto
                        <input //Etiqueta de ingreso de datos, la cual posee los siguientes atriutos y propiedades
                            id="email" //Selector identificador, con valor aignado de una cadena de texto, la cual es la misma que su "label" a enlazar
                            type="email" //Propiedad de tipo, con valor para ser de "correo electrónico"
                            name="email" //Atributo de "nombre", con valor de dicha cadena de texto la cual es la misma declarada en la propiedad "initialValues" de la instancia de Formik, para enlazar sus valores
                            **value={formData.values.email}** //Atributo de "valor", con valo dentro de llaves por ser código de JS, siendo desde la instancia de Formik "formData", acceder a sus "valores" los cuales son los que se encuentran en la propiedad "initialValues" de la instancia de Formik, accediendo a la propiedad "email" de dicha propiedad "initialValues" para obetener su valor
                            **onChange={formData.handleChange}** //Propiedad manejadora de ventos del evento de "cambio de valor" en éste input, con valor asignado de, dentro de llaves por ser código de JS, desde la instancia de Formik "formData", ejecutar su función manejadora de dicho evento la cual es una función interna de React que maneja el cambio de valor en el campo de entrada y actualiza el estado del componente 
                            required //"requerido" para ser un campo obligatorio y no puede enviarse vacío
                        />
                    </div>
    
                    <div> //Etiqueta contenedora de bloque
                        <label htmlFor="firstName">First Name</label> //Etiqueta para etiquetar elementos de interfaz de usuario, posee el atributo "for" para enlazarla con el elemento correspondiente con valor de una cadena de texto la cual es la misma que el identificador del elemento a ser enlazado, y contiene texto
                        <input //Etiqueta de ingreso de datos, la cual posee los siguientes atriutos y propiedades
                            id="firstName" //Selector identificador, con valor aignado de una cadena de texto, la cual es la misma que su "label" a enlazar
                            type="text" //Propiedad de tipo, con valor para ser de "texto"
                            name="firstName" //Atributo de "nombre", con valor de dicha cadena de texto la cual es la misma declarada en la propiedad "initialValues" de la instancia de Formik, para enlazar sus valores
                            **value={formData.values.firstName}** //Atributo de "valor", con valor dentro de llaves por ser código de JS, siendo desde la instancia de Formik "formData", acceder a sus "valores" los cuales son los que se encuentran en la propiedad "initialValues" de la instancia de Formik, accediendo a la propiedad "firstName" de dicha propiedad "initialValues" para obetener su valor
                            **onChange={formData.handleChange}** //Propiedad manejadora de ventos del evento de "cambio de valor" en éste input, con valor asignado de, dentro de llaves por ser código de JS, desde la instancia de Formik "formData", ejecutar su función manejadora de dicho evento la cual es una función interna de React que maneja el cambio de valor en el campo de entrada y actualiza el estado del componente 
                            required //"requerido" para ser un campo obligatorio y no puede enviarse vacío
                        />
                    </div>
    
                    <div> //Etiqueta contenedora de bloque
                        <label htmlFor="lastName">Last Name</label> //Etiqueta para etiquetar elementos de interfaz de usuario, posee el atributo "for" para enlazarla con el elemento correspondiente con valor de una cadena de texto la cual es la misma que el identificador del elemento a ser enlazado, y contiene texto
                        <input //Etiqueta de ingreso de datos, la cual posee los siguientes atriutos y propiedades
                            id="lastName" //Selector identificador, con valor aignado de una cadena de texto, la cual es la misma que su "label" a enlazar
                            type="text" //Propiedad de tipo, con valor para ser de "texto"
                            name="lastName" //Atributo de "nombre", con valor de dicha cadena de texto la cual es la misma declarada en la propiedad "initialValues" de la instancia de Formik, para enlazar sus valores
                            **value={formData.values.lastName}** //Atributo de "valor", con valor dentro de llaves por ser código de JS, siendo desde la instancia de Formik "formData", acceder a sus "valores" los cuales son los que se encuentran en la propiedad "initialValues" de la instancia de Formik, accediendo a la propiedad "lastName" de dicha propiedad "initialValues" para obetener su valor
                            **onChange={formData.handleChange}** //Propiedad manejadora de ventos del evento de "cambio de valor" en éste input, con valor asignado de, dentro de llaves por ser código de JS, desde la instancia de Formik "formData", ejecutar su función manejadora de dicho evento la cual es una función interna de React que maneja el cambio de valor en el campo de entrada y actualiza el estado del componente 
                            required //"requerido" para ser un campo obligatorio y no puede enviarse vacío
                        />
                    </div>
                    <button type="submit">Subscribe</button> //Etiqueta de botón, posee el atributo de "tipo" con valor de "entregar" para mandar los valores del formulario, y contiene texto
                </form>
            </div>
        );
    }
    ```
    

# FORMA DINÁMICA DE USO:

- Los campos dependen de otros campos para ser mostrados, utilizando condicionales preferente utilizando el **operador** ************************ternario************************ “ ************************?  :************************ ”
- **Se hacen validaciones:**
    - Dentro de la instancia creada de Formik al usar el hook “******************useFormik******************”, se puede colocar la propiedad “****************validate****************” la cual manejará las validaciones de los campos del formulario.
    - Dicha propiedad puede recibir como valor una función de flecha callback o la referencia de una función creada para manejar las validaciones del formulario la cual puede ser nombrada arbitrariamente.
        - Dicha función para manejar las validaciones del formulario recibe como argumento   un objeto "**values**" que contiene los valores actuales de todos los campos del formulario.
        - Dicha función para manejar las validaciones del formulario, ejecuta la declaración de una constante “************errors************” la cual va a contener los mensajes de errores al cumplir una condición validación, ésta constante tiene valor asignado de un objeto.
        - El objeto de la constante “************errors************” recibirá sus propiedades y valores al cumplirse una condición de validación, para ello:
            1. Lo que ejecuta la  condición es acceder al objeto “************errors************”.
            2. Colocar el nombre del control del formulario de cuál se está haciendo la validación, siendo el mismo nombre que se encuentra en la propiedad “**initialValues**” de la instancia de Formik.
            3. Asignar como valor, una cadena de texto que será mostrada al cumplir la condición de validación.
    - Después se crean las condicionales para validar cada control del formulario, accediendo al objeto “**values**” y al nombre del control que se encuentra en la propiedad “**initialValues**” de la instancia de Formik, así creando una validación personalizada.
    - Finalmente se ****************retorna**************** el objeto “************errors************” con todas sus propiedades y valores dependientes de las condicionales para validar los valores de los controles del formulario.
    
    ### EJEMPLO:
    
    ```jsx
    import { useFormik } from "formik";  //Se importa la función hook para el manejo de formularios, desde, la librería de "formik"
    
    export default function App() { //Se exporta como valor por defecto, la declaración de función que será un componente, la cual ejecuta el siguiente bloque
        const formData = useFormik({ //Declaración de constante que será el controlador del formulario, siendo una instancia de "Formik" que almacena el estado y las funciones relacionadas con el formulario con valor asignado de, la función hook "useFormik", que configura varias opciones importantes mediante un objeto que recibe como argumento un obejto que posee las siguientes propiedades
            initialValues: { //Propiedad del objeto, la cual será los valores iniciales de los inputs/controles del fomulario, con valor de un objeto con las siguientes propiedades
                email: "", //Propiedad del objeto, que será el valor inicial para el control de "email", con valor asignado de, una cadena vacía 
                firstName: "", //Propiedad del objeto, que será el valor inicial para el control de "firstName", con valor asignado de, una cadena vacía 
                lastName: "", //Propiedad del objeto, que será el valor inicial para el control de "lastName", con valor asignado de, una cadena vacía 
                termsAccepted: false //Propiedad del objeto, que será el valor inicial para el control de "termsAccepted", con valor asignado de, una cadena vacía 
            },
            **onSubmit: handleSubmit**, //Propiedad del objeto, que será una función que se ejecutará cuando el formulario sea enviado, con valor asignado de, la función declarada para manejar el envío de los datos del formulario
            **validate: handleValidate** //Propiedad del objeto, que manejará las validaciones de los campos del formulario, con valor asignado de, la función declarada para manejar las validaciones de los campos del formulario.
        });
    
        function handleSubmit(values) { //Declaración de función para manejar el envío de los datos del formulario, la cual recibe como argumento un objeto "values" que contiene los valores actuales de todos los campos del formulario, y que ejecuta el siguiente bloque
            console.log(values); //A la consola del navegador, se le aplica el métdo para imprir en la misma, los valores del dicho objeto "values" enviado como argumento
            formData.resetForm();  //A dicha instancia de "Formik" la cual hace referencia a los valores del formulario, se le aplica el método proporcionado por la misma instancia, para resetear el formulario y todos sus campos
        }
    
        **function handleValidate(values) {** //Declaración de función para manejar las validaciones de los campos del formulario., la cual recibe como argumento un objeto "values" que contiene los valores actuales de todos los campos del formulario, y que ejecuta el siguiente bloque
            **const errors = {};** //Declaración de constante con valor asignado de, un objeto, la cual va a contener los mensajes de errores al cumplir una condición validación
    
            **if (values.termsAccepted === false) {** //Condicional que valida si, del objeto de valores del formulario, acceder al valor del control "termsAccepted", es estrictamente igual, que el valor booleano "false", ejecutando el siguiente bloque
                **errors.termsAccepted = "You must accept the terms";** //Se accede a la constante objeto que contendrá los errores por validaciones, asignando una nueva propiedad que hace referencia al control "termsAccepted", con valor asignado de, la cadena de texto "Required", para indicar que es requerido por estar vacío
            **}**
    
            **if (values.firstName.length === 0) {** //Condicional que valida si, del objeto de valores del formulario, acceder al valor del control "firstName", y obtener su longitud, es estrictamente igual, que el valor numérico 0, ejecutando el siguiente bloque
                **errors.firstName = "Required";** //Se accede a la constante objeto que contendrá los errores por validaciones, asignando una nueva propiedad que hace referencia al control "firstName", con valor asignado de, la cadena de texto "Required", para indicar que es requerido por estar vacío
    						**} else if (values.firstName.length < 2) {** //Si no se cumple la condición anterior, significando que si se validó con éxito, ahora se valida si, del objeto de valores del formulario, acceder al valor del control "firstName", y obtener su longitud, es menor que el valor numérico 2, ejecutando el siguiente bloque
                **errors.firstName = "Should be more than 2 characters";** //Se accede a la constante objeto que contendrá los errores por validaciones, asignando una nueva propiedad que hace referencia al control "firstName", con valor asignado de, la cadena de texto "Should be more than 2 characters", para indicar que el valor ingresado debe ser mayor que dos carácteres
            }
          
            **if (values.lastName.length === 0) {** //Condicional que valida si, del objeto de valores del formulario, acceder al valor del control "lastName", y obtener su longitud, es estrictamente igual, que el valor numérico 0, ejecutando el siguiente bloque
                **errors.lastName = "Required";** //Se accede a la constante objeto que contendrá los errores por validaciones, asignando una nueva propiedad que hace referencia al control "lastName", con valor asignado de, la cadena de texto "Required", para indicar que es requerido por estar vacío
            **} else if (values.lastName.length < 2) {** //Si no se cumple la condición anterior, significando que si se validó con éxito, ahora se valida si, del objeto de valores del formulario, acceder al valor del control "lastName", y obtener su longitud, es menor que el valor numérico 2, ejecutando el siguiente bloque
                **errors.lastName = "Should be more than 2 characters";** //Se accede a la constante objeto que contendrá los errores por validaciones, asignando una nueva propiedad que hace referencia al control "lastName", con valor asignado de, la cadena de texto "Should be more than 2 characters", para indicar que el valor ingresado debe ser mayor que dos carácteres
            **}
          
            if (values.email.length === 0) {** //Condicional que valida si, del objeto de valores del formulario, acceder al valor del control "email", y obtener su longitud, es estrictamente igual, que el valor numérico 0, ejecutando el siguiente bloque
                **errors.email = "Required";** //Se accede a la constante objeto que contendrá los errores por validaciones, asignando una nueva propiedad que hace referencia al control "email", con valor asignado de, la cadena de texto "Required", para indicar que es requerido por estar vacío
            **} else if (!/[a-z0-9]+@[a-z]+\.[a-z]{2,3}/i.test(values.email)) {** //Si no se cumple la condición anterior, significando que si se validó con éxito, ahora se valida si, NO("!/") se cumple la expresión regular "[a-z0-9]", Coincide con uno o más caracteres alfabéticos en minúsculas o dígitos, "@" Coincide con el carácter "@", "[a-z]" Coincide con uno o más caracteres alfabéticos en minúsculas (dominio), "\." Coincide con el carácter punto ("."), "[a-z]{2,3}" Coincide con dos o tres caracteres alfabéticos en minúsculas (extensión de dominio), el modificador "i" al final de la expresión regular indica que la coincidencia no debe ser sensible a mayúsculas y minúsculas, siendo que a dicha expresión regular se le aplica el método de "probar" dicha expresión regular, la cual recibe como argumento, del objeto de valores del formulario, acceder al valor del control "email", para obtener dicho valor y problarlo para validarlo, para asegurarse de que tenga un formato válido, ejecutando el siguiente bloque si se cumple la condición anterior
                **errors.email = "Invalid email";** //Se accede a la constante objeto que contendrá los errores por validaciones, asignando una nueva propiedad que hace referencia al control "email", con valor asignado de, la cadena de texto "Invalid ****email", para indicar que no es un formato válido de correo electróico
            **}
          
            return errors;** //Se retorna, el objeto de errores con todas sus propiedades y valores asignadas pependiendo de los resultados de las condicionales para validar los valores de los controles del formulario
        **}**
    
    		function handleDisabled() { //Declaración de función para manejar el comportamiento de habilitar el botón para enviar los datos del formulario, la cual ejecuta el siguiente bloque
            return Object.keys(formData.errors).length > 0 || //Se retorna el resultado de dos condiciones siendo, desde la clase "Object" ejecutar su método "keys" para obtener un arreglo de las propiedades (claves) de un objeto, el cual recibe como argumento, de la instacia de Forimik "formData", acceder al objeto de errores de validaciones, la cual es accedida automáticamente mediante la propiedad "validate" de la instancia de Formirk que ejecuta la función asociada "handleValidate" que retorna el objeto "errors", y obtener su longitud que representa la cantidad de errores de validación presentes para validar si es mayor que 0 lo que significa que hay errores, O, la siguiente condición
            !Object.values(formData.values).every(value => value); //Negar(invertir) el resultado de, desde la clase "Object" ejecutar su método "values" para obtener un arreglo de los valores de las propiedades de un objeto, el cual recibe como argumento, de la instacia de Forimik "formData", acceder a sus "valores" los cuales son los que se encuentran en la propiedad "initialValues" de la instancia de Formik, y aplicar el método "every" que verifica si todos los elementos de un arreglo cumplen con cierta condición, siendo cada uno de los valores dentro del objeto "initialValues", el cual recibe como argumento una función flecha callback, la cual ejecuta, por cada valor dentro del arreglo obtenido del objeto "formData.values", retornar el mismo valor, así para verificar si todos los valores en el objeto "formData.values" son verdaderos, siendo que si todos los valores son verdaderos, la función "every" devolverá "true", si al menos un valor es falso, la función "every" devolverá "false", al agregar la negación "!" al principio, se invierte el resultado, por lo que la expresión completa evalúa si al menos un valor es "falso"
        }
    
        return ( //Se retorna una estructura de JSX, el cual será la sección principal del componente a ser renderizado, siendo colocado entre paréntesis
            <div> //Etiqueta contenedora de bloque
                <h1>Dynamic Form</h1> //Etiqueta de título principal, contiene texto
                **<form onSubmit={formData.handleSubmit}>** //Etiquta de formulario, la cual posee la propiedad manejadora de ventos del evento de "entregar/enviar" los datos del formulario, con valor asignado de, dentro de llaves por ser código de JS, desde la instancia de Formik "formData", ejecutar su función manejadora de dicho evento la cual hace refencia a la propiedad "onSubmit" de dicha instancia "formData"
                    <div> //Etiqueta contenedora de bloque
                        <label htmlFor="termsAccepted">Accept Terms</label> //Etiqueta para etiquetar elementos de interfaz de usuario, posee el atributo "for" para enlazarla con el elemento correspondiente con valor de una cadena de texto la cual es la misma que el identificador del elemento a ser enlazado, y contiene texto
                        <input //Etiqueta de ingreso de datos, la cual posee los siguientes atriutos y propiedades
                            type="checkbox" //Propiedad de tipo, con valor para ser de "caja de selección"
                            name="termsAccepted" //Atributo de "nombre", con valor de dicha cadena de texto la cual es la misma declarada en la propiedad "initialValues" de la instancia de Formik, para enlazar sus valores
                            id="termsAccepted" //Selector identificador, con valor aignado de una cadena de texto, la cual es la misma que su "label" a enlazar
                            checked={formData.values.termsAccepted} //Propiedad de "comprobado/seleccionado", con valor dentro de llaves por ser código de JS, desde la instancia de Formik "formData", acceder a sus "valores" los cuales son los que se encuentran en la propiedad "initialValues" de la instancia de Formik, accediendo a la propiedad "termsAccepted" de dicha propiedad "initialValues" para obetener su valor y controlar su comportamiento dependiendo de dicho valor
                            value={formData.values.termsAccepted} //Atributo de "valor", con valor dentro de llaves por ser código de JS, desde la instancia de Formik "formData", acceder a sus "valores" los cuales son los que se encuentran en la propiedad "initialValues" de la instancia de Formik, accediendo a la propiedad "termsAccepted" de dicha propiedad "initialValues" para obetener su valor y controlar su comportamiento dependiendo de dicho valor
                            onChange={formData.handleChange} //Propiedad manejadora de ventos del evento de "cambio de valor" en éste input, con valor asignado de, dentro de llaves por ser código de JS, desde la instancia de Formik "formData", ejecutar su función manejadora de dicho evento la cual es una función interna de React que maneja el cambio de valor en el campo de entrada y actualiza el estado del componente 
                            required //"requerido" para ser un campo obligatorio y no puede enviarse vacío
                        />
    
                        **{formData.errors.termsAccepted ? (** //Dentro de llaves por se código de JS, se utiliza el operador ternario, que valida, si, desde la instancia de Formik "formData", acceder al objeto de errores de validaciones, la cual es accedida automáticamente mediante la propiedad "validate" de la instancia de Formirk que ejecuta la función asociada "handleValidate" que retorna el objeto "errors", del cual se accede a su propiedad "termsAccepted" ejecutando las validaciones correspondientes mediante las condicionales, siendo que si alguna de ellas se cumple con su valor booleano "true", ejecuta el siguiente bloque, el cual es una estructura JSX
                            **<div style={{ color: "red" }}>** //Etiqueta contendora de bloque, con la propiedad de "estilos" con valor asignado dentro de llaves por ser código de JS, dentro de un objeto, colocar la propiedad de color de texto con valor asignado del color rojo, para todo los elementos dentro de dicho contenedor, el cual contiene lo siguiente
                                **{formData.errors.termsAccepted}** //Dentro de llaves por ser código de JS, desde la instancia de Formik "formData", acceder al objeto de errores de validaciones, la cual es accedida automáticamente mediante la propiedad "validate" de la instancia de Formirk que ejecuta la función asociada "handleValidate" que retorna el objeto "errors", del cual se accede a su propiedad "termsAccepted" ejecutando las validaciones correspondientes mediante las condicionales, siendo que si alguna de ellas se cumple, se mostrará el valor de la condición que se ejecute, la cual es alguna validación que no ha sido exitosa
                            **</div>
                        ) : null}** //Si no se cumple la condición ternaria, se ejecuta un valor nulo para no mostrar nada, lo que significa que no hubo errores al validar el campo
                    </div>
    
                    <div> //Etiqueta contenedora de bloque
                        <label htmlFor="email">Email</label> //Etiqueta para etiquetar elementos de interfaz de usuario, posee el atributo "for" para enlazarla con el elemento correspondiente con valor de una cadena de texto la cual es la misma que el identificador del elemento a ser enlazado, y contiene texto
                        <input //Etiqueta de ingreso de datos, la cual posee los siguientes atributos y propiedades
                            id="email" //Selector identificador, con valor aignado de una cadena de texto, la cual es la misma que su "label" a enlazar
                            type="email" //Propiedad de tipo, con valor para ser de "correo electrónico"
                            name="email" //Atributo de "nombre", con valor de dicha cadena de texto la cual es la misma declarada en la propiedad "initialValues" de la instancia de Formik, para enlazar sus valores
                            placeholder="sample@mail.com" //Propiedad de texto demostrativo, con valor de una cadena de texto a ser mostrada
                            value={formData.values.email} //Atributo de "valor", con valor dentro de llaves por ser código de JS, desde la instancia de Formik "formData", acceder a sus "valores" los cuales son los que se encuentran en la propiedad "initialValues" de la instancia de Formik, accediendo a la propiedad "email" de dicha propiedad "initialValues" para obetener su valor y controlar su comportamiento dependiendo de dicho valor
                            onChange={formData.handleChange} //Propiedad manejadora de ventos del evento de "cambio de valor" en éste input, con valor asignado de, dentro de llaves por ser código de JS, desde la instancia de Formik "formData", ejecutar su función manejadora de dicho evento la cual es una función interna de React que maneja el cambio de valor en el campo de entrada y actualiza el estado del componente 
                            onBlur={formData.handleBlur} //Propiedad manejadora de ventos del evento de "desenfoque" en éste input, con valor asignado de, dentro de llaves por ser código de JS, desde la instancia de Formik "formData", ejecutar su función manejadora de dicho evento la cual es una función interna de React que maneja el desenfoque del elemento y actualiza el estado del componente 
                            required //"requerido" para ser un campo obligatorio y no puede enviarse vacío
                        />
    
                        **{formData.touched.email &&** //Dentro de llaves por se código de JS, se ejecutan dos condiciones que deben ser cumplidas al mismo  tiempo, siendo la primera, desde la instancia de Formik "formData", acceder a su propiedad "touched" que verifica si algún campo/control del formulario ha sido "tocado" o interactuado por el usuario (en términos de enfoque y pérdida de enfoque) para mostrar el error después de perder el enfoque del campo, siendo el campo/control "email", y al mismo tiempo mediante el operador "and/&&"
                        **formData.errors.email ? (** //Se utiliza el operador ternario, que valida, si, desde la instancia de Formik "formData", acceder al objeto de errores de validaciones, la cual es accedida automáticamente mediante la propiedad "validate" de la instancia de Formirk que ejecuta la función asociada "handleValidate" que retorna el objeto "errors", del cual se accede a su propiedad "email" ejecutando las validaciones correspondientes mediante las condicionales, siendo que si alguna de ellas se cumple con su valor booleano "true", ejecuta el siguiente bloque, el cual es una estructura JSX
                            **<div style={{ color: "red" }}>** //Etiqueta contendora de bloque, con la propiedad de "estilos" con valor asignado dentro de llaves por ser código de JS, dentro de un objeto, colocar la propiedad de color de texto con valor asignado del color rojo, para todo los elementos dentro de dicho contenedor, el cual contiene lo siguiente
                                **{formData.errors.email}** //Dentro de llaves por ser código de JS, desde la instancia de Formik "formData", acceder al objeto de errores de validaciones, la cual es accedida automáticamente mediante la propiedad "validate" de la instancia de Formirk que ejecuta la función asociada "handleValidate" que retorna el objeto "errors", del cual se accede a su propiedad "email" ejecutando las validaciones correspondientes mediante las condicionales, siendo que si alguna de ellas se cumple, se mostrará el valor de la condición que se ejecute, la cual es alguna validación que no ha sido exitosa
                            **</div>
                        ) : null}** //Si no se cumple la condición ternaria, se ejecuta un valor nulo para no mostrar nada, lo que significa que no hubo errores al validar el campo
                    </div>
    
                    **{!formData.errors.email &&** //Dentro de llaves por se código de JS, se ejecutan dos condiciones que deben ser cumplidas al mismo tiempo, siendo la primera, negar/invertir el valor obtenido de, desde la instancia de Formik "formData", acceder al objeto de errores de validaciones, la cual es accedida automáticamente mediante la propiedad "validate" de la instancia de Formirk que ejecuta la función asociada "handleValidate" que retorna el objeto "errors", del cual se accede a su propiedad "email" ejecutando las validaciones correspondientes mediante las condicionales, siendo que si alguna de ellas se cumple, será invertido el valor "true" por "false" para que no se cumpla la condición, y al mismo tiempo mediante el operador "and/&&"
                    **formData.values.termsAccepted === true ? (** //Desde la instancia de Formik "formData", acceder a sus "valores" los cuales son los que se encuentran en la propiedad "initialValues" de la instancia de Formik, accediendo a la propiedad "termsAccepted" de dicha propiedad "initialValues" para obetener su valor, y validar si es estrictamente igual que, el valor booleano "true", éstas dos condiciones se deden de cumplir para, retornar una estructura de JSX, siendo colocado entre paréntesis
                        <> //Fragmento de React para contener el componente sin ser renderizado dentro de otro elemento
                            <div> //Etiqueta contenedora de bloque
                                <label htmlFor="firstName">First Name</label> //Etiqueta para etiquetar elementos de interfaz de usuario, posee el atributo "for" para enlazarla con el elemento correspondiente con valor de una cadena de texto la cual es la misma que el identificador del elemento a ser enlazado, y contiene texto
                                <input //Etiqueta de ingreso de datos, la cual posee los siguientes atributos y propiedades
                                    type="text" //Propiedad de tipo, con valor para ser de "texto"
                                    name="firstName" //Atributo de "nombre", con valor de dicha cadena de texto la cual es la misma declarada en la propiedad "initialValues" de la instancia de Formik, para enlazar sus valores
                                    id="firstName" //Selector identificador, con valor aignado de una cadena de texto, la cual es la misma que su "label" a enlazar
                                    value={formData.values.firstName} //Atributo de "valor", con valor dentro de llaves por ser código de JS, desde la instancia de Formik "formData", acceder a sus "valores" los cuales son los que se encuentran en la propiedad "initialValues" de la instancia de Formik, accediendo a la propiedad "firstName" de dicha propiedad "initialValues" para obtener su valor y controlar su el valor mostrado dependiendo de dicho valor
                                    onChange={formData.handleChange} //Propiedad manejadora de ventos del evento de "cambio de valor" en éste input, con valor asignado de, dentro de llaves por ser código de JS, desde la instancia de Formik "formData", ejecutar su función manejadora de dicho evento la cual es una función interna de React que maneja el cambio de valor en el campo de entrada y actualiza el estado del componente
                                    onBlur={formData.handleBlur} //Propiedad manejadora de ventos del evento de "desenfoque" en éste input, con valor asignado de, dentro de llaves por ser código de JS, desde la instancia de Formik "formData", ejecutar su función manejadora de dicho evento la cual es una función interna de React que maneja el desenfoque del elemento y actualiza el estado del componente
                                    required //"requerido" para ser un campo obligatorio y no puede enviarse vacío
                                />
    
                                **{formData.touched.firstName &&** //Dentro de llaves por se código de JS, se ejecutan dos condiciones que deben ser cumplidas al mismo  tiempo, siendo la primera, desde la instancia de Formik "formData", acceder a su propiedad "touched" que verifica si algún campo/control del formulario ha sido "tocado" o interactuado por el usuario (en términos de enfoque y pérdida de enfoque) para mostrar el error después de perder el enfoque del campo, siendo el campo/control "firstName", y al mismo tiempo mediante el operador "and/&&"
                                **formData.errors.firstName ? (** //Se utiliza el operador ternario, que valida, si, desde la instancia de Formik "formData", acceder al objeto de errores de validaciones, la cual es accedida automáticamente mediante la propiedad "validate" de la instancia de Formirk que ejecuta la función asociada "handleValidate" que retorna el objeto "errors", del cual se accede a su propiedad "firstName" ejecutando las validaciones correspondientes mediante las condicionales, siendo que si alguna de ellas se cumple con su valor booleano "true", ejecuta el siguiente bloque, el cual es una estructura JSX
                                    **<div style={{ color: "red" }}>** //Etiqueta contendora de bloque, con la propiedad de "estilos" con valor asignado dentro de llaves por ser código de JS, dentro de un objeto, colocar la propiedad de color de texto con valor asignado del color rojo, para todo los elementos dentro de dicho contenedor, el cual contiene lo siguiente
                                        **{formData.errors.firstName}** //Dentro de llaves por ser código de JS, desde la instancia de Formik "formData", acceder al objeto de errores de validaciones, la cual es accedida automáticamente mediante la propiedad "validate" de la instancia de Formirk que ejecuta la función asociada "handleValidate" que retorna el objeto "errors", del cual se accede a su propiedad "firstName" ejecutando las validaciones correspondientes mediante las condicionales, siendo que si alguna de ellas se cumple, se mostrará el valor de la condición que se ejecute, la cual es alguna validación que no ha sido exitosa
                                    **</div>
                                ) : null}** //Si no se cumple la condición ternaria, se ejecuta un valor nulo para no mostrar nada, lo que significa que no hubo errores al validar el campo
                            </div>
    
                            <div> //Etiqueta contenedora de bloque
                                <label htmlFor="lastName">Last Name</label> //Etiqueta para etiquetar elementos de interfaz de usuario, posee el atributo "for" para enlazarla con el elemento correspondiente con valor de una cadena de texto la cual es la misma que el identificador del elemento a ser enlazado, y contiene texto
                                <input //Etiqueta de ingreso de datos, la cual posee los siguientes atributos y propiedades
                                    type="text" //Propiedad de tipo, con valor para ser de "texto"
    
                                    name="lastName" //Atributo de "nombre", con valor de dicha cadena de texto la cual es la misma declarada en la propiedad "initialValues" de la instancia de Formik, para enlazar sus valores
                                    id="lastName" //Selector identificador, con valor aignado de una cadena de texto, la cual es la misma que su "label" a enlazar
                                    value={formData.values.lastName} //Atributo de "valor", con valor dentro de llaves por ser código de JS, desde la instancia de Formik "formData", acceder a sus "valores" los cuales son los que se encuentran en la propiedad "initialValues" de la instancia de Formik, accediendo a la propiedad "lastName" de dicha propiedad "initialValues" para obtener su valor y controlar su el valor mostrado dependiendo de dicho valor
                                    onChange={formData.handleChange} //Propiedad manejadora de ventos del evento de "cambio de valor" en éste input, con valor asignado de, dentro de llaves por ser código de JS, desde la instancia de Formik "formData", ejecutar su función manejadora de dicho evento la cual es una función interna de React que maneja el cambio de valor en el campo de entrada y actualiza el estado del componente
                                    onBlur={formData.handleBlur} //Propiedad manejadora de ventos del evento de "desenfoque" en éste input, con valor asignado de, dentro de llaves por ser código de JS, desde la instancia de Formik "formData", ejecutar su función manejadora de dicho evento la cual es una función interna de React que maneja el desenfoque del elemento y actualiza el estado del componente
                                    required //"requerido" para ser un campo obligatorio y no puede enviarse vacío
                                />
    
                                **{formData.touched.lastName &&** //Dentro de llaves por se código de JS, se ejecutan dos condiciones que deben ser cumplidas al mismo  tiempo, siendo la primera, desde la instancia de Formik "formData", acceder a su propiedad "touched" que verifica si algún campo/control del formulario ha sido "tocado" o interactuado por el usuario (en términos de enfoque y pérdida de enfoque) para mostrar el error después de perder el enfoque del campo, siendo el campo/control "lastName", y al mismo tiempo mediante el operador "and/&&"
                                **formData.errors.lastName ? (** //Se utiliza el operador ternario, que valida, si, desde la instancia de Formik "formData", acceder al objeto de errores de validaciones, la cual es accedida automáticamente mediante la propiedad "validate" de la instancia de Formirk que ejecuta la función asociada "handleValidate" que retorna el objeto "errors", del cual se accede a su propiedad "lastName" ejecutando las validaciones correspondientes mediante las condicionales, siendo que si alguna de ellas se cumple con su valor booleano "true", ejecuta el siguiente bloque, el cual es una estructura JSX
                                    **<div style={{ color: "red" }}>** //Etiqueta contendora de bloque, con la propiedad de "estilos" con valor asignado dentro de llaves por ser código de JS, dentro de un objeto, colocar la propiedad de color de texto con valor asignado del color rojo, para todo los elementos dentro de dicho contenedor, el cual contiene lo siguiente
                                        **{formData.errors.lastName}** //Dentro de llaves por ser código de JS, desde la instancia de Formik "formData", acceder al objeto de errores de validaciones, la cual es accedida automáticamente mediante la propiedad "validate" de la instancia de Formirk que ejecuta la función asociada "handleValidate" que retorna el objeto "errors", del cual se accede a su propiedad "lastName" ejecutando las validaciones correspondientes mediante las condicionales, siendo que si alguna de ellas se cumple, se mostrará el valor de la condición que se ejecute, la cual es alguna validación que no ha sido exitosa
                                    **</div>
                                ) : null}** //Si no se cumple la condición ternaria, se ejecuta un valor nulo para no mostrar nada, lo que significa que no hubo errores al validar el campo
                            </div>
                        </>
                    **) : null}** //Si no se cumple la condición ternaria, se ejecuta un valor nulo para no mostrar nada, lo que significa que no se han aceptado los terminos y no se ha escrito un correo electrónico
                    
                    <button //Etiqueta de botón, que se encargará de mandar los datos del formulario, contiene los siguiente atributos y propiedades
                        type="submit" //Propiedad de tipo, con valor para ser de "entregar/mandar"
                        name="submit" //Atributo de "nombre", con valor de dicha cadena de texto la cual serán mandada con los datos del formulario
                        disabled={handleDisabled()}> //Propiedad de "desactivado", con valor asignado dentro de llaves por ser código de JS, de llamar a ejecutar dicha función para habilitar el botón dependiendo del buen llenado de los campos del formulario
                        Subscribe //Contiene texto a ser mostrado
                    </button>
                </form>
            </div>
        );
    }
    ```
    

# CÓDIGO REFACTORIZADO:

## Funciones y componentes de Formik:

- **getFieldsProps() function:**
    - Permite reducir props repetido como **name**, **value**, **onChange**, **onBlur.**
    - Como propiedad de un elementos, dentro de llaves “****{}****” por ser código de JS, se colocan la sintaxis de spread operator “**…**” para extender todas las propiedades en el control, seguido del nombre de la instancia de Formik, y ejecutando su método “**getFieldsProps()**”.
    - Como argumentos para la función “**getFieldsProps()**”, se recibe el valor de la propiedad “********name********” correspondiente al elemento/control, el cual se definió en la propiedad “**initialValues**” de la instancia de Formik.
- **Formik component:**
    - Es un componente que encierra todo el formulario en un contexto en lugar de usar el hook **useFormik.**
    - Para utilizarlo, se coloca como etiqueta HTML la palabra Formik, la cual será una etiqueta de apertura y cierre “**<Formik></Formik>**” que será un componente que contendrá la etiqueta de formulario “**<form></form>**”.
    - Dicha etiqueta de apertura “**<Formik >**” recibirá como props, los valores de la misma manera que se colocaban en el hook “**useFormik**”, los cuales deben de ser asignados dentro de llaves por ser código de JS.
    - Lo que contienen las etiquetas “**<Formik></Formik>**”:
        - Una función que retorna un componente JSX de formulario, para ello, dentro de llaves “****{}****” por ser código de JS, se coloca una función de flecha, la cual va a recibir como argumento un objeto “****************formData****************” que posee las misma propiedades y métodos que los que retorna la función hook “******************useFormik******************” que retornan dichas etiquetas “**<Formik></Formik>**” y el cual será utilizado dentro del formulario para acceder a los valores enviados como props a dichas etiquetas.
        - Si no se va a utiliza el objeto “**formData**”, no es necesario ejecutar dicha función dentro del componente “**<Formik>**”, sino que solo se coloca el componente formulario correspondiente.
- **Form component:**
    - Devuelve una etiqueta **form** con todos los props de Formik (handleSubmit, handleReset).
    - Para delimitar y agrupar elementos del formulario. Actúa como un contenedor que engloba todos los campos de entrada, etiquetas y otros elementos relacionados con el formulario.
    - Para utilizarlo, se debe importar “********Form********” desde la librería “************formik************”.
    - En vez de utilizar la etiqueta “**<form>**” de HTML, se utiliza como etiqueta “**<Form>**”, la cual no necesita recibir la propiedad que maneja el evento “**onSubmit**” ya que la contiene implícitamente mediante la propiedad “**onSubmit**” enviada al componente “**<Formik>**”.
- **Field component:**
    - Devuelve una etiqueta **input** con todos los props de la función “getFieldProps()”,  permitiendo NO colocar: **{...formData.getFieldProps("nameControl")}**
    - Para utilizarlo, se debe importar “********Field********” desde la librería “************formik************”.
    - En vez de utilizar una etiqueta “**<input >**”, se utiliza como etiqueta “**<Field >**” la cual va a recibir las mismas propiedades que dicho input, siendo obligatoria la propiedad “********name********” la cual debe tener como valor asignado, el mismo valor declarado en la propiedad “**initialValues**” del componente “**<Formik>**”.
- **ErrorMessage component:**
    - Agrega la condición cuando **input** es usado (touched) y si existe el error para mostrar un mensaje, desde el objeto “************errors************” el cual es accedido automáticamente mediante la propiedad "**validate**" del componente “**<Formik>**”.
    - Para utilizarlo, se coloca como etiqueta “**<ErrorMessage name=””/>**”, la cual en la propiedad “********name********” debe tener como valor asignado, el mismo valor declarado en la propiedad “**initialValues**” del componente “**<Formik>**” para ejecutar sus validaciones.
- **setFieldValue() function:**
    - Permite actualizar los values del estado del formulario.
- **FieldArray component:**
    - Ayuda a manejar arrays dentro de los values del form.
- **useFormikContext component:**
    - Custom hook que te permite acceder a los valor del contexto del componente Formik.

## Yup:

- Librería open-source.
- Permite construir esquemas(objetos) de validación, en los cuales se declaran lo nombres que hacen referencia a los controles del formulario para así declarar exactamente que validaciones debe de cumplir, mediante el uso de funciones integradas para dichas validaciones.
- Integración con Formik (recomendada).
- Para implementarlo, mediante la terminal se debe posicionar en la ruta del proyecto e instalar la librería mediante ******npm******, con el comando:
    
    ```
    **npm install yup**
    ```
    
- Para utilizarlo, se debe importar todo “*****”, de “****as****”, “******Yup******”, desde la librería “******yup******”.
    
    ```jsx
    **import * as Yup from "yup";**
    ```
    
- Se crear el esquema de validación, el cual es una constante declarada arbitrariamente, con valor asignado de, dede la clase “******Yup******”, ejecutar su método de objeto “************object()************” y aplicar el método “**************shape()**************” para darle forma/formato:
- El formato del esquema de validación mediante el método “**************shape()**************” se define de la siguiente manera:
    - Se coloca como propiedad del objeto, el nombre que hace referencia al control del formulario, el cual debe declarase igual que en la propiedad “**initialValues**” del componente “**<Formik>**” para enlazarlos.
    - Como valor de dicho control del formulario, se asigna, desde la clase “******Yup******”, la validación que debe de cumplir, como: “**Yup.string()**”, para validar que sea una cadena de texto.
    - Para añadir más validaciones, se encadenan las funciones para validar lo demás que se requiere, siendo: “**Yup.string().required().email()**”, para validar que sea una cadena de texto, que es una campo requerido, y que debe ser un correo electrónico.
        
        Dentro de cada función de validación, se puede recibir como argumento, una cadena de texto para definir los mensajes que se mostrarán si no se cumplen las validaciones.
        
        Así para cada control/campo del formulario.
        
- Para utilizar el formato del esquema de validación, se coloca en el componente “**<Formik>**” como la propiedad “********************************validationSchema********************************” a la cual se le asigna como valor, dentro de llaves por ser código de JS, el nombre de la constante  donde se definió el formato del esquema de validación.

### EJEMPLO:

```jsx
**import { Formik, Form, Field, ErrorMessage } from "formik";** //Se importan, el componente que encierra todo el formulario en un contexto, el componente para crear fomrularios de Formik, el componente para controles/campos del formulario, y el componente para mostrar errores de validaciones, desde la libreía de "formik".
**import * as Yup from "yup";** //Se importa "todo" de Yup, desde la librería "yup" para manejar las validaciones de los campos dek formulario.

export default function App() { //Se exporta como valor por defecto, la declaración de función que será un componente, la cual ejecuta el siguiente bloque.

    function handleSubmit(values, **{ resetForm }**) { //Declaración de función para manejar el envío de los datos del formulario, la cual recibe como primer argumento el objeto "values" que contiene los valores actuales de todos los campos del formulario, como segundo argumento se destructura desde el objeto “formikBag” la funicón para resetear el formualrio, y que ejecuta el siguiente bloque.
        console.log(values); //A la consola del navegador, se le aplica el métdo para imprir en la misma, los valores del dicho objeto "values" enviado como argumento.
        **resetForm();** //Se ejecuta la función para resetear el formulario.
    }

	function handleDisabled(formData) { //Declaración de función para manejar el comportamiento de habilitar el botón para enviar los datos del formulario, la cual ejecuta el siguiente bloque.
        return Object.keys(formData.errors).length > 0 || //Se retorna el resultado de dos condiciones siendo, desde la clase "Object" ejecutar su método "keys" para obtener un arreglo de las propiedades (claves) de un objeto, el cual recibe como argumento, de la instacia de Forimik "formData", acceder al objeto de errores de validaciones, la cual es accedida automáticamente mediante la propiedad "validate" de la instancia de Formirk que ejecuta la función asociada "handleValidate" que retorna el objeto "errors", y obtener su longitud que representa la cantidad de errores de validación presentes para validar si es mayor que 0 lo que significa que hay errores, O, la siguiente condición.
            !Object.values(formData.values).every(value => value); //Negar(invertir) el resultado de, desde la clase "Object" ejecutar su método "values" para obtener un arreglo de los valores de las propiedades de un objeto, el cual recibe como argumento, de la instacia de Forimik "formData", acceder a sus "valores" los cuales son los que se encuentran en la propiedad "initialValues" de la instancia de Formik, y aplicar el método "every" que verifica si todos los elementos de un arreglo cumplen con cierta condición, siendo cada uno de los valores dentro del objeto "initialValues", el cual recibe como argumento una función flecha callback, la cual ejecuta, por cada valor dentro del arreglo obtenido del objeto "formData.values", retornar el mismo valor, así para verificar si todos los valores en el objeto "formData.values" son verdaderos, siendo que si todos los valores son verdaderos, la función "every" devolverá "true", si al menos un valor es falso, la función "every" devolverá "false", al agregar la negación "!" al principio, se invierte el resultado, por lo que la expresión completa evalúa si al menos un valor es "falso".
    }

    **const FormSchema = Yup.object().shape({** //Declaración de constante con valor asignado de, desde "Yup", ejecutar su método para crear un objeto, al cual se le aplica el método, para darle una forma/formato, el cual recibe como argumento un obejto, el cual será el objeto de validaciones de los controles/campos del formulario.
        **termsAccepted: Yup.boolean().oneOf([true], "Is required").required(),** //Propiedad del objeto, el cual será el validador del campo "termsAccepted", el cual está definido de la misma manera que en la propiedad "initialValues**"** del componente “<Formik>”, con valor asignado de, desde "Yup", validar que se reciba un valor booleano, y con el método "oneOf" que asegura que éste campo tenga exactamente el valor "true", si no es así, se muestra el mensaje de error "Is required", esto garantiza que el campo esté seleccionado para que el formulario sea válido.
        **email: Yup.string().required("Is required").email("Is not a valid email"),** //Propiedad del objeto, el cual será el validador del campo "email", el cual está definido de la misma manera que en la propiedad "initialValues**"** del componente “<Formik>”, con valor asignado de, desde "Yup", validar que se reciba un valor de cadena de texto, que sea requerido mostrando la cadena de texto enviada como argumento al momento que no se cumpla dicha validación, y se valida que el valor del campo sea una dirección de correo electrónico válida y muestra el mensaje de error "Is not a valid email" si no lo es.
        **firstName: Yup.string().required("Is required").min(2, "Minimum two characters"),** //Propiedad del objeto, el cual será el validador del campo "firstName", el cual está definido de la misma manera que en la propiedad "initialValues**"** del componente “<Formik>”, con valor asignado de, desde "Yup", validar que se reciba un valor de cadena de texto, que sea requerido mostrando la cadena de texto enviada como argumento al momento que no se cumpla dicha validación, y se valida que el valor del campo tener una longitud mínima de 2 caracteres, si no se cumplen estas condiciones, se mostrará el mensaje de error "Minimum two characters".
        **lastName: Yup.string().required("Is required").min(2, "Minimum two characters")** //Propiedad del objeto, el cual será el validador del campo "lastName", el cual está definido de la misma manera que en la propiedad "initialValues**"** del componente “<Formik>”, con valor asignado de, desde "Yup", validar que se reciba un valor de cadena de texto, que sea requerido mostrando la cadena de texto enviada como argumento al momento que no se cumpla dicha validación, y se valida que el valor del campo tener una longitud mínima de 2 caracteres, si no se cumplen estas condiciones, se mostrará el mensaje de error "Minimum two characters".
    **});**

    return ( //Se retorna una estructura de JSX, el cual será la sección principal del componente a ser renderizado, siendo colocado entre paréntesis.
        <div> //Etiqueta contenedora de bloque.
            <h1>Dynamic Form</h1> //Etiqueta de título principal, contiene texto.
            **<Formik** //Componente que encierra todo el formulario en un contexto, el cual recibe las siguientes props.
                **initialValues={{** //Propiedad para definir los valores iniciales de los campos del formulario, con valor asignado dentro de paréntesis por ser código de JS, de un objeto con las siguientes propiedades.
                    **termsAccepted: false,** //Propiedad del objeto, que será el valor inicial para el control de "termsAccepted", con valor asignado de, el valor booleano false, para que el control no empiece activado.
                    **email: "",** //Propiedad del objeto, que será el valor inicial para el control de "email", con valor asignado de, una cadena vacía.
                    **firstName: "",** //Propiedad del objeto, que será el valor inicial para el control de "firstName", con valor asignado de, una cadena vacía.
                    **lastName: "",** //Propiedad del objeto, que será el valor inicial para el control de "lastName", con valor asignado de, una cadena vacía.
                **}}
                onSubmit={handleSubmit}** //Propiedad del objeto, que será una función que se ejecutará cuando el formulario sea enviado, con valor asignado dentro de llaves por ser código de JS, de la función declarada para manejar el envío de los datos del formulario.
                **validationSchema={FormSchema} >** //Propiedad del objeto, que manejará la validaciones, siendo el esquema de validaciones creado con Yup, con valor asignado dentro de llaves por ser código de JS, de dicha constante la cual es el esquema de validaciones definido para validar los campos del formulario.
                
                **{(formData) => (** //El componente "<Formik>" contiene, dentro de llaves por ser código de JS, una función de flecha de renderizado como hijo, la cual recibe como argumento el objeto “formData” que retorna dicho componenete “<Formik>” y el cual será utilizado dentro del formulario para acceder a los valores enviados como props a dicho componente "<Formik>", y que retorna una estructura de JSX.
                    **<Form>** //Componente con todos las props del componenete “<Formik>”, para delimitar y agrupar elementos del formulario. Actúa como un contenedor que engloba todos los campos de entrada, etiquetas y otros elementos relacionados con el formulario.
                        <div> //Etiqueta contenedora de bloque.
                            <label htmlFor="termsAccepted">Accept Terms</label> //Etiqueta para etiquetar elementos de interfaz de usuario, posee el atributo "for" para enlazarla con el elemento correspondiente con valor de una cadena de texto la cual es la misma que el identificador del elemento a ser enlazado, y contiene texto. 
                            **<Field** //Componente de campo/control dentro de formulario, el cual contiene las sisguientes props.
                                type="checkbox" //Propiedad de "tipo", con valor para ser de "caja de selección".
                                name="termsAccepted" //Atributo de "nombre", con valor de dicha cadena de texto la cual es la misma declarada en la propiedad "initialValues" del componente <Formik>, para enlazar sus valores.
                                id="termsAccepted" //Selector identificador, con valor aignado de una cadena de texto, la cual es la misma que su "label" a enlazar.
                                checked={formData.values.termsAccepted} //Propiedad de "comprobado/seleccionado", con valor dentro de llaves por ser código de JS, desde el objeto "formData", acceder a sus "valores" los cuales son los que se encuentran en la propiedad "initialValues" del componente <Formik>, accediendo a la propiedad "termsAccepted" de dicha propiedad "initialValues" para obetener su valor y controlar su comportamiento dependiendo de dicho valor.
                            **/>**
                            **<ErrorMessage name="termsAccepted" />** //Componente de mensaje de error, siendo que agrega la condición cuando el control/campo es usado (touched) y si existe el error para mostrar un mensaje, desde el objeto “errors” el cual es accedido automáticamente mediante la propiedad "validate" del componente “<Formik>”, posee la propiedad de "nombre" con el mismo valor declarado en la propiedad “initialValues” del componente “<Formik>” para ejecutar sus validaciones.
                        </div>

                        <div> //Etiqueta contenedora de bloque.
                            <label htmlFor="email">Email</label> //Etiqueta para etiquetar elementos de interfaz de usuario, posee el atributo "for" para enlazarla con el elemento correspondiente con valor de una cadena de texto la cual es la misma que el identificador del elemento a ser enlazado, y contiene texto. 
                            **<Field** //Componente de campo/control dentro de formulario, el cual contiene las sisguientes props.
                                type="email" //Propiedad de "tipo", con valor para ser de "correo electrónico".
                                name="email" //Atributo de "nombre", con valor de dicha cadena de texto la cual es la misma declarada en la propiedad "initialValues" del componente <Formik>, para enlazar sus valores.
                                id="email" //Selector identificador, con valor aignado de una cadena de texto, la cual es la misma que su "label" a enlazar.                                
                                placeholder="sample@mail.com" //Propiedad de texto demostrativo, con valor de una cadena de texto a ser mostrada.
                            **/>**
                            **<ErrorMessage name="email" />** //Componente de mensaje de error, siendo que agrega la condición cuando el control/campo es usado (touched) y si existe el error para mostrar un mensaje, desde el objeto “errors” el cual es accedido automáticamente mediante la propiedad "validate" del componente “<Formik>”, posee la propiedad de "nombre" con el mismo valor declarado en la propiedad “initialValues” del componente “<Formik>” para ejecutar sus validaciones.
                        </div>

                        {!formData.errors.email && //Dentro de llaves por se código de JS, se ejecutan dos condiciones que deben ser cumplidas al mismo tiempo, siendo la primera, negar/invertir el valor obtenido de, desde la instancia de Formik "formData", acceder al objeto de errores de validaciones, la cual es accedida automáticamente mediante la propiedad "validate" de la instancia de Formirk que ejecuta la función asociada "handleValidate" que retorna el objeto "errors", del cual se accede a su propiedad "email" ejecutando las validaciones correspondientes mediante las condicionales, siendo que si alguna de ellas se cumple, será invertido el valor "true" por "false" para que no se cumpla la condición, y al mismo tiempo mediante el operador "and/&&".
                        formData.values.termsAccepted === true ? ( //Desde la instancia de Formik "formData", acceder a sus "valores" los cuales son los que se encuentran en la propiedad "initialValues" de la instancia de Formik, accediendo a la propiedad "termsAccepted" de dicha propiedad "initialValues" para obetener su valor, y validar si es estrictamente igual que, el valor booleano "true", éstas dos condiciones se deden de cumplir para, retornar una estructura de JSX, siendo colocado entre paréntesis.
                            <> //Fragmento de React para contener el componente sin ser renderizado dentro de otro elemento.
                                <div> //Etiqueta contenedora de bloque.
                                    <label htmlFor="firstName">First Name</label> //Etiqueta para etiquetar elementos de interfaz de usuario, posee el atributo "for" para enlazarla con el elemento correspondiente con valor de una cadena de texto la cual es la misma que el identificador del elemento a ser enlazado, y contiene texto.
                                    **<Field** //Componente de campo/control dentro de formulario, el cual contiene las sisguientes props.
                                        type="text" //Propiedad de "tipo", con valor para ser de "texto".
                                        name="firstName" //Atributo de "nombre", con valor de dicha cadena de texto la cual es la misma declarada en la propiedad "initialValues" del componente <Formik>, para enlazar sus valores.
                                        id="firstName" //Selector identificador, con valor aignado de una cadena de texto, la cual es la misma que su "label" a enlazar.
                                    **/>
                                    <ErrorMessage name="firstName" />** //Componente de mensaje de error, siendo que agrega la condición cuando el control/campo es usado (touched) y si existe el error para mostrar un mensaje, desde el objeto “errors” el cual es accedido automáticamente mediante la propiedad "validate" del componente “<Formik>”, posee la propiedad de "nombre" con el mismo valor declarado en la propiedad “initialValues” del componente “<Formik>” para ejecutar sus validaciones.
                                </div>

                                <div> //Etiqueta contenedora de bloque.
                                    <label htmlFor="lastName">Last Name</label> //Etiqueta para etiquetar elementos de interfaz de usuario, posee el atributo "for" para enlazarla con el elemento correspondiente con valor de una cadena de texto la cual es la misma que el identificador del elemento a ser enlazado, y contiene texto.
                                    **<Field** //Componente de campo/control dentro de formulario, el cual contiene las sisguientes props.
                                        type="text" //Propiedad de "tipo", con valor para ser de "texto".
                                        name="lastName" //Atributo de "nombre", con valor de dicha cadena de texto la cual es la misma declarada en la propiedad "initialValues" del componente <Formik>, para enlazar sus valores.
                                        id="lastName" //Selector identificador, con valor aignado de una cadena de texto, la cual es la misma que su "label" a enlazar.
                                    **/>
                                    <ErrorMessage name="lastName" />** //Componente de mensaje de error, siendo que agrega la condición cuando el control/campo es usado (touched) y si existe el error para mostrar un mensaje, desde el objeto “errors” el cual es accedido automáticamente mediante la propiedad "validate" del componente “<Formik>”, posee la propiedad de "nombre" con el mismo valor declarado en la propiedad “initialValues” del componente “<Formik>” para ejecutar sus validaciones.
                                </div>
                            </>
                        ) : null} //Si no se cumple la condición ternaria, se ejecuta un valor nulo para no mostrar nada, lo que significa que no se han aceptado los terminos y no se ha escrito un correo electrónico.
                        
                        <button //Etiqueta de botón, que se encargará de mandar los datos del formulario, contiene los siguiente atributos y propiedades.
                            type="submit" //Propiedad de tipo, con valor para ser de "entregar/mandar".
                            name="submit" //Atributo de "nombre", con valor de dicha cadena de texto la cual serán mandada con los datos del formulario.
                            disabled={handleDisabled(formData)}> //Propiedad de "desactivado", con valor asignado dentro de llaves por ser código de JS, de llamar a ejecutar dicha función para habilitar el botón dependiendo del buen llenado de los campos del formulario.
                            Subscribe //Contiene texto a ser mostrado.
                        </button>
                    **</Form>**
                )}
            **</Formik>**
        </div>
    );
}
```