La utilización de una u otra librería para la parte del Front-End de los desarrollos que hemos implementado, es algo que decide cada desarrollador. Esto nos proporciona una gran libertad, pero también una gran responsabilidad. La elección de una mala librería es problema del desarrollador y por lo tanto, los errores o bugs que pueda tener, serán problema de quien utilice esta librería. En este artículo vamos a ver si en nuestros desarrollos deberíamos incluir Redux Form, cuáles son sus pros y sus contras.
Desde hace más de un año seleccionamos ReactJS como la librería utilizada para la parte Front-End de los desarrollos que hemos implementado. Una de sus principales ventajas es la posibilidad de elegir cada parte de nuestro desarrollo, ReactJS se encarga solo del renderizado del HTML.
Hace una única cosa y la hace muy bien. Junto con ReactJS hay una serie de librerías que complementan todo lo que nos proporciona un Framework Javascript: react-redux, react-router, react-thunks…
Qué es Redux-Form
Partiendo de está introducción, en nuestros desarrollos estábamos teniendo un problema a nivel de mantenimiento del código en todos los componentes React que se comportan como Formularios. Para implementar este componente, tenemos una serie de elementos en su estado que hay que controlar. Todo esto, hace que cuando el formulario tiene muchos campos y se requieren una serie de validaciones, el número de líneas crece exponencialmente.
Para intentar solucionar este problema, nos planteamos:
- Intentar incorporar una libreria de validaciones
- Crear componentes con dicha funcionalidad
- Incorporar React-Redux
Descartamos incorporar una librería de validaciones porque suponía añadir una dependencia extra, y no nos terminaba de convencer su funcionamiento.
La segunda opción (crear componente con dicha funcionalidad), nos pareció una muy buena opción debido a que nosotros teníamos todo el control del desarrollo, pero parecía que estábamos reconstruyendo la rueda y añadiendo una dificultad extra a nuestros desarrollos.
Consideraciones previas
En medio de esta situación, probamos Redux-Form…pero antes de empezar a hablar sobre esta librería vamos a hacer algunas aclaraciones:
- Está vinculado a la librería react-redux, por lo que si no utilizas esta librería para implementar una arquitectura «Flux», no la puedes utilizar (a no ser que hagas modificaciones).
- No es una librería que nos sirva unos formularios predefinidos. El desarrollo de los formularios lo tenemos que hacer nosotros. Quizá el nombre lleve a equivocación.
- Utiliza el patron Hight Order Componente (aka llamado Matriuska).
- Se intregra con la Store.
Beneficios
El gran beneficio que nos reporta esta librería, es que pone orden al código para utilizar en los formularios. Por un lado tenemos un componente Formulario que es el que vinculamos con nuestra store. Por otro lado tenemos una serie de componente para poder tener cada campo con una validación. Y por si fuera poco, todas estas reglas se pueden compartir entre los mismos campos, por ejemplo tenemos una función que nos valide un DNI y esta regla la podemos utilizar en más campos.
El Flujo de nuestra aplicación quedaría de la siguiente forma:
Show me the code, talk (write) is cheap
Para empezar, en nuestra solución incorporaremos las librería redux-form y sus tipos correspondientes (debido que durante el desarrollo hemos optado por usar Typescript en lugar de Javascript directamente). Para ello, en el package.json de nuestro proyecto añadiremos estas dependencias:
@types/redux-form": "^7.4.6", redux-form": "^7.4.2"
Otra forma de incorporar estas dependencias es instalando estos paquetes con npm y la opcion –save-dev.
Una vez tenemos la solución lista, creamos nuestro formulario. En primer lugar, vamos a crearnos un componente personalizado extendiendo la funcionalidad Field que nos proporciona la librería en el que vamos a configurar, por un lado las reglas de validación que va a tener el campo, la etiqueta, el mensaje de error de validación. Un ejemplo sería el siguiente código:
const email = (value:any) => value && !/^[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,4}$/i.test(value) ? 'Invalid email address' : undefined const alphaNumeric = (value:any) => value && /[^a-zA-Z0-9 ]/i.test(value) ? 'Only alphanumeric characters' : undefined export const phoneNumber = (value:any) => value && !/^(0|[1-9][0-9]{9})$/i.test(value) ? 'Invalid phone number, must be 10 digits' : undefined const renderField = (props:any) => ( <div className="col-md-3 col-sm-3 aitscontactw3l-grid aitscontactw3l-grid-1"> <label className="fill fill-top">{props.label}</label> <input className="fill" {...props.input} placeholder={props.label} type={props.type} /> {props.touched && ((props.error && <span>{props.error}</span>) || (props.warning && <span>{props.warning}</span>))} </div>
Con este campo personalizado y con estas reglas de validación, ya podemos empezar a crear el formulario. Para ello lo que vamos a utilizar es el componente Field, que se comportará según nuestros criterios, es decir: qué reglas de validación van a tener, cuál es su diseño, etc.
Por otro lado en este componente también vamos a ver cual es el funcionamiento que queremos hacer una vez nuestro formulario sea válido. Un ejemplo de un formulario de suscripción a un rss podría ser de la siguiente forma:
onst ContactForm = (props:any) => { const { handleSubmit } = props return ( <div className="aitscontactw3l" id="aitscontactw3l"> <div className="container"> <h3>Contacto</h3> <form onSubmit={handleSubmit}> <Field type="email" name="Email" component={renderField} label="Correo electronico" validate={[required, email]} warn={alphaNumeric} /> <input className="submit" type="submit" value="Enviar" /> <div className="clearfix"/> </form> </div> </div> )
Una vez ya tenemos el formulario, tenemos que registrarlo en la librería para que se pueda utilizar como un elemento más dentro del flujo de la aplicación.
export const Form = reduxForm({ // a unique name for the form form: 'contact' })(ContactForm)
Como ya hemos comentado, el nombre de form debe de ser único, es decir, si damos de alta dos formularios con el mismo identificador, la librería no funciona.
Uno de los aspectos que he esbozado al inicio del artículo, es que Redux-Form hace uso del patrón hight order component. Esto lo podemos comprobar porque ahora mismo, hemos creado un componente y éste va a estar incluido en un componente superior desde el cual se le van a pasar las props (en forma de Matriuska). Por lo que en nuestro desarrollo lo que vamos a realizar es crearnos un componente principal que será el encargado de pasarle los métodos de ejecución al hijo. Un ejemplo del anterior sería el siguiente código:
export class Contact extends React.Component<{}, {}> { public submit = (values:any) => { console.log(values) } public render() { return <Form onSubmit={this.submit} /> } }
Por último para poder incluir Redux-Form en el contexto de Redux lo que tenemos que hacer es incluirlo dentro de los Reducers correspondiente. La librería ya trae de serie un reducer «formReducer» que es el que vamos a utilizar.
import { reducer as formReducer } from 'redux-form' export interface IStateReducer { carrousel:ICarrouselItem[], form:any } export const state = combineReducers<IStateReducer>({ carrousel: carrouselReducer, form: formReducer });
¿Aún hay más?
La librería aun tiene mucha más funcionalidad avanzada, por ejemplo puede hacernos agrupaciones de campos para aplicar validaciones. También tiene funcionalidad para poder implementar un Wizard. Con esta herramienta hace todo de una forma más sencilla.
Resumen
Redux Form es una librería que nos facilita la posibilidad de establecer el orden de nuestra solución para todos los componentes que se comporten de tipo formulario. Esto hace mucho más fácil su posterior mantenimiento y evolución.
Otra de las grandes ventajas es que lo tenemos incorporado a Redux, lo que hace que todo siga el mismo patrón Flux. En definitiva, a la hora de incorporar librerías de terceros siempre hay que pensarlo muy detenidamente porque nos puede ocasionar problemas futuros. Sin embargo, Redux Form es una librería bastante buena que nos aporta numerosos beneficios y en el caso de formularios complejos, nos facilita mucho la vida 😊