{"data":{"allMarkdownRemark":{"edges":[{"node":{"id":"800a446b-0861-54ed-a2e3-a36e545abef1","frontmatter":{"category":"Coding","title":"The concept of SubForms - with React and Formik","date":"2019-07-02","summary":"Create forms at scale with Formik and Yup","thumbnail":{"relativePath":"pages/the-concept-of-subforms-with-formik/thumbnail.png","childImageSharp":{"resolutions":{"base64":"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAQCAYAAAAWGF8bAAAACXBIWXMAAAsSAAALEgHS3X78AAABcklEQVQ4y51UzcqCQBSdN+st3AluXOTel6htL2FBuDDaBFGRZGSEuOiHoKI2RbXsR/N83AFjkMbsuzCMjHfOnHvOnWHIRJIk71k2xLxssE+LsmSK1+uVC8pkYLTxdrvh8XjwOf3+dqgU8H6/o9PpYDAYwPd9TCYTuK6L6XSaCyoFfD6fsCwL3W4Xi8UC8/kc2+2Wg8dx/DsgMWw0GqjX6+j3+2i1WhiPx/8vmRjato3hcIjdbof9fs+Zinm5DLPOkQnNZpOzdBwHYRi+zcpzmmXZiQnX6xXL5RKbzYbrl2qXzRX3sE+aHA4HXC6XjxpFUYTj8SjVkokNS3E6naCqKi8zCAKsViveKqTlaDTi7VOpVNBut7nOUoYp4Hq9hmEYqNVqKJfLUBQF1WqVH6LrOkzThKZpKJVKOJ/P30umUkk3SiZDqFVIgtlsxtc9z0Ov1+P9mZYu6smK3mFZSDUUHUvbglxN2yQ76F8hl/OerSJP2R9ITMR6qwehxQAAAABJRU5ErkJggg==","width":395,"height":325,"src":"/static/631a33919834353b3dda8e8578592a5b/b3029/thumbnail.png","srcSet":"/static/631a33919834353b3dda8e8578592a5b/b3029/thumbnail.png 1x,\n/static/631a33919834353b3dda8e8578592a5b/8d141/thumbnail.png 1.5x,\n/static/631a33919834353b3dda8e8578592a5b/ee72c/thumbnail.png 2x"}}},"authorName":"Nicholas Peretti","authorDescription":"Software Engineer","authorAvatar":{"relativePath":"pages/the-concept-of-subforms-with-formik/avatar.jpg","childImageSharp":{"resolutions":{"base64":"data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAAUABQDASIAAhEBAxEB/8QAFwABAQEBAAAAAAAAAAAAAAAAAAMFBP/EABQBAQAAAAAAAAAAAAAAAAAAAAD/2gAMAwEAAhADEAAAAcKk+4zgAAf/xAAZEAEAAgMAAAAAAAAAAAAAAAACAQMQEiD/2gAIAQEAAQUCJlJVI4M6oXGs8f/EABQRAQAAAAAAAAAAAAAAAAAAACD/2gAIAQMBAT8BH//EABQRAQAAAAAAAAAAAAAAAAAAACD/2gAIAQIBAT8BH//EABsQAQACAgMAAAAAAAAAAAAAAAEAAhAgITFC/9oACAEBAAY/AgO2cmBlvTbX/8QAGxABAQACAwEAAAAAAAAAAAAAAREAIRAgQVH/2gAIAQEAAT8hBOpDNUohZx7hMll+40df/9oADAMBAAIAAwAAABBDwAD/xAAUEQEAAAAAAAAAAAAAAAAAAAAg/9oACAEDAQE/EB//xAAUEQEAAAAAAAAAAAAAAAAAAAAg/9oACAECAQE/EB//xAAcEAEBAAICAwAAAAAAAAAAAAABESFBADEQIFH/2gAIAQEAAT8QxBALK8VVkQLA7X54WBCyOzfKvBj0MduVz6//2Q==","width":50,"height":50,"src":"/static/9347eae31d09e05f032d02892f955d38/d2d31/avatar.jpg","srcSet":"/static/9347eae31d09e05f032d02892f955d38/d2d31/avatar.jpg 1x,\n/static/9347eae31d09e05f032d02892f955d38/0b804/avatar.jpg 1.5x,\n/static/9347eae31d09e05f032d02892f955d38/753c3/avatar.jpg 2x,\n/static/9347eae31d09e05f032d02892f955d38/31ca8/avatar.jpg 3x"}}},"headerImage":{"relativePath":"pages/the-concept-of-subforms-with-formik/headerImage.png","childImageSharp":{"resolutions":{"base64":"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAGCAIAAABM9SnKAAAACXBIWXMAAAsSAAALEgHS3X78AAAAUUlEQVQY06WOIQ4AMQgE+/8nYSoQaExFRQmSH4AovX7gkiM3djOZbecH7W2IiDGGqu69y7K7997NrFzOzLXWnFNEbrwm36vMjIgAQETl2194AJcvYFpZxM6mAAAAAElFTkSuQmCC","width":1280,"height":384,"src":"/static/8ce613d93c9ee2f1e3b248f2aabe8efc/26421/headerImage.png","srcSet":"/static/8ce613d93c9ee2f1e3b248f2aabe8efc/26421/headerImage.png 1x,\n/static/8ce613d93c9ee2f1e3b248f2aabe8efc/34a7a/headerImage.png 1.5x"}}}},"html":"<p>In the last few months I’ve been working a lot with forms. I had to do a large refactoring in one of AUTO1’s applications, and through all the research, I also encountered the term <strong>subform</strong>. The concept was troublesome not only for me.\nI found more than one issue on the Formik repository about developers asking for help.\nIn this article I'll try to clarify this concept and show you how to use it properly.</p>\n<h2>What the heck is a subform anyway?</h2>\n<p>If you’ve ever worked on a medium-large project with a reasonable amount of forms, you might have probably noticed that you could potentially reuse a lot of fields, sometimes even entire forms!\nThat’s the core of the subform concept: reusable components (fields or group of fields) that can be composed together to create bigger forms.</p>\n<p>At the beginning I had a lot of questions in my mind like:</p>\n<ul>\n<li>How can I handle validation?</li>\n<li>How can I handle form state?</li>\n<li>How can I stay flexible?</li>\n</ul>\n<p>These questions and many others appeared while I was refactoring existing codebase. Many similar questions created by other developers appeared in the Formik repository as issues.</p>\n<p>Don’t get me wrong: implementing scalable validation for a single form is not that hard. The complicated thing is to keep validation and state flexible while you write your subforms. What does it mean? We’ll see that in a moment.</p>\n<h2>How Formik can help</h2>\n<p>Formik is an amazing library, one of the bests for this job, and here’s what it brings to the table:</p>\n<h3>Auto-connected Field component</h3>\n<p>Formik provides a Field component that, thanks to the React Context API, will be automatically connected to the Form component that wraps our Field, regardless of how deep our Field is in the tree.</p>\n<h3>Yup validation schema</h3>\n<p>Yup is a library to create validation schemas. This library is very similar to the prop-types of React, so it is very simple to start using it.\nFormik supports Yup natively, so you just need to define the schema and pass it to Formik, it will take care of the rest.</p>\n<p>So this is how Formik will make our life easier not only while creating subforms but also when we’ll need to maintain them!</p>\n<h2>Enough talking, show me the code</h2>\n<p>Let’s create our first subform! Before we start, we need to clarify what <strong>our subform will be responsible</strong> for:</p>\n<ul>\n<li>Provide a basic validation schema</li>\n<li>Provide some default values (required by Formik)</li>\n<li>Provide the list of its fields (in case we need to access the data from outside, as we’ll see later)</li>\n<li>Provide a React component that will render the subform to the user and its fields’ errors</li>\n</ul>\n<p>In our case, we're going to create a form that allows to create a new user.\nWe'll need to display the following fields:</p>\n<ul>\n<li>First name</li>\n<li>Last name</li>\n<li>Email</li>\n<li>Password</li>\n</ul>\n<p>Just keep it simple. So, let’s create our <code class=\"language-text\">NewUserSubForm</code> directory and our <code class=\"language-text\">fieldsNames</code> file. It’s just a file that exports constants, don’t worry. It will look like this:</p>\n<div class=\"gatsby-highlight\" data-language=\"javascript\"><pre class=\"language-javascript\"><code class=\"language-javascript\"><span class=\"token comment\">//  UserSubform/fieldsNames.js</span>\n<span class=\"token keyword\">export</span> <span class=\"token keyword\">const</span> <span class=\"token constant\">FIRST_NAME</span> <span class=\"token operator\">=</span> <span class=\"token string\">'firstName'</span>\n<span class=\"token keyword\">export</span> <span class=\"token keyword\">const</span> <span class=\"token constant\">LAST_NAME</span> <span class=\"token operator\">=</span> <span class=\"token string\">'lastName'</span>\n<span class=\"token keyword\">export</span> <span class=\"token keyword\">const</span> <span class=\"token constant\">EMAIL</span> <span class=\"token operator\">=</span> <span class=\"token string\">'email'</span>\n<span class=\"token keyword\">export</span> <span class=\"token keyword\">const</span> <span class=\"token constant\">PASSWORD</span> <span class=\"token operator\">=</span> <span class=\"token string\">'password'</span></code></pre></div>\n<h3>Defining the validation schema</h3>\n<div class=\"gatsby-highlight\" data-language=\"javascript\"><pre class=\"language-javascript\"><code class=\"language-javascript\"><span class=\"token comment\">//  UserSubform/validationSchema.js</span>\n<span class=\"token keyword\">import</span> <span class=\"token operator\">*</span> <span class=\"token keyword\">as</span> yup <span class=\"token keyword\">from</span> <span class=\"token string\">'yup'</span>\n<span class=\"token keyword\">import</span> <span class=\"token punctuation\">{</span> <span class=\"token constant\">FIRST_NAME</span><span class=\"token punctuation\">,</span> <span class=\"token constant\">LAST_NAME</span><span class=\"token punctuation\">,</span> <span class=\"token constant\">EMAIL</span><span class=\"token punctuation\">,</span> <span class=\"token constant\">PASSWORD</span> <span class=\"token punctuation\">}</span> <span class=\"token keyword\">from</span> <span class=\"token string\">'./fieldsNames'</span>\n\n<span class=\"token keyword\">const</span> <span class=\"token constant\">MIN_PASSWORD_LENGTH</span> <span class=\"token operator\">=</span> <span class=\"token number\">8</span>\n\n<span class=\"token keyword\">const</span> <span class=\"token constant\">REQUIRED_MESSAGE</span> <span class=\"token operator\">=</span> <span class=\"token string\">'This field is required'</span>\n<span class=\"token keyword\">const</span> <span class=\"token constant\">INVALID_EMAIL_FORMAT</span> <span class=\"token operator\">=</span> <span class=\"token string\">'Invalid email format'</span>\n<span class=\"token keyword\">const</span> <span class=\"token constant\">PASSWORD_TOO_SHOWRT</span> <span class=\"token operator\">=</span> <span class=\"token template-string\"><span class=\"token template-punctuation string\">`</span><span class=\"token string\">The password must be at least </span><span class=\"token interpolation\"><span class=\"token interpolation-punctuation punctuation\">${</span><span class=\"token constant\">MIN_PASSWORD_LENGTH</span><span class=\"token interpolation-punctuation punctuation\">}</span></span><span class=\"token string\"> characters long</span><span class=\"token template-punctuation string\">`</span></span>\n\n<span class=\"token keyword\">export</span> <span class=\"token keyword\">default</span> yup<span class=\"token punctuation\">.</span><span class=\"token function\">object</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">{</span>\n  <span class=\"token punctuation\">[</span><span class=\"token constant\">FIRST_NAME</span><span class=\"token punctuation\">]</span><span class=\"token operator\">:</span> yup<span class=\"token punctuation\">.</span><span class=\"token function\">string</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">required</span><span class=\"token punctuation\">(</span><span class=\"token constant\">REQUIRED_MESSAGE</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span>\n  <span class=\"token punctuation\">[</span><span class=\"token constant\">LAST_NAME</span><span class=\"token punctuation\">]</span><span class=\"token operator\">:</span> yup<span class=\"token punctuation\">.</span><span class=\"token function\">string</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">required</span><span class=\"token punctuation\">(</span><span class=\"token constant\">REQUIRED_MESSAGE</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span>\n  <span class=\"token punctuation\">[</span><span class=\"token constant\">EMAIL</span><span class=\"token punctuation\">]</span><span class=\"token operator\">:</span> yup\n    <span class=\"token punctuation\">.</span><span class=\"token function\">string</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span>\n    <span class=\"token punctuation\">.</span><span class=\"token function\">required</span><span class=\"token punctuation\">(</span><span class=\"token constant\">REQUIRED_MESSAGE</span><span class=\"token punctuation\">)</span>\n    <span class=\"token punctuation\">.</span><span class=\"token function\">email</span><span class=\"token punctuation\">(</span><span class=\"token constant\">INVALID_EMAIL_FORMAT</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span>\n  <span class=\"token punctuation\">[</span><span class=\"token constant\">PASSWORD</span><span class=\"token punctuation\">]</span><span class=\"token operator\">:</span> yup\n    <span class=\"token punctuation\">.</span><span class=\"token function\">string</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span>\n    <span class=\"token punctuation\">.</span><span class=\"token function\">required</span><span class=\"token punctuation\">(</span><span class=\"token constant\">REQUIRED_MESSAGE</span><span class=\"token punctuation\">)</span>\n    <span class=\"token punctuation\">.</span><span class=\"token function\">min</span><span class=\"token punctuation\">(</span><span class=\"token constant\">MIN_PASSWORD_LENGTH</span><span class=\"token punctuation\">,</span> <span class=\"token constant\">PASSWORD_TOO_SHOWRT</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span>\n<span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span></code></pre></div>\n<p>We’ve just defined our validation schema regardless the markup of our form. This file just contains all the validation logic and has one responsibility. If in the future we’ll need to add some more validation options, we’ll just need to change it here.</p>\n<p>Now it’s time for the default values. Initial values are <strong>required</strong> from Formik because it uses controlled inputs. So, if you don’t specify those values, you’ll get and error from React as soon as you try to change the content of the input.</p>\n<div class=\"gatsby-highlight\" data-language=\"javascript\"><pre class=\"language-javascript\"><code class=\"language-javascript\"><span class=\"token comment\">//  UserSubform/defaultValues.js</span>\n<span class=\"token keyword\">import</span> <span class=\"token punctuation\">{</span> <span class=\"token constant\">FIRST_NAME</span><span class=\"token punctuation\">,</span> <span class=\"token constant\">LAST_NAME</span><span class=\"token punctuation\">,</span> <span class=\"token constant\">EMAIL</span><span class=\"token punctuation\">,</span> <span class=\"token constant\">PASSWORD</span> <span class=\"token punctuation\">}</span> <span class=\"token keyword\">from</span> <span class=\"token string\">'./fieldsNames'</span>\n\n<span class=\"token keyword\">export</span> <span class=\"token keyword\">default</span> <span class=\"token punctuation\">{</span>\n  <span class=\"token punctuation\">[</span><span class=\"token constant\">FIRST_NAME</span><span class=\"token punctuation\">]</span><span class=\"token operator\">:</span> <span class=\"token string\">''</span><span class=\"token punctuation\">,</span>\n  <span class=\"token punctuation\">[</span><span class=\"token constant\">LAST_NAME</span><span class=\"token punctuation\">]</span><span class=\"token operator\">:</span> <span class=\"token string\">''</span><span class=\"token punctuation\">,</span>\n  <span class=\"token punctuation\">[</span><span class=\"token constant\">EMAIL</span><span class=\"token punctuation\">]</span><span class=\"token operator\">:</span> <span class=\"token string\">''</span><span class=\"token punctuation\">,</span>\n  <span class=\"token punctuation\">[</span><span class=\"token constant\">PASSWORD</span><span class=\"token punctuation\">]</span><span class=\"token operator\">:</span> <span class=\"token string\">''</span><span class=\"token punctuation\">,</span>\n<span class=\"token punctuation\">}</span></code></pre></div>\n<h3>Rendering the subform</h3>\n<p>And now the master piece: The React component. Remember: <strong>we just need to use the Fields and not the Formik or the Form components</strong>.</p>\n<div class=\"gatsby-highlight\" data-language=\"javascript\"><pre class=\"language-javascript\"><code class=\"language-javascript\"><span class=\"token comment\">//  UserSubform/index.js</span>\n<span class=\"token keyword\">import</span> React<span class=\"token punctuation\">,</span> <span class=\"token punctuation\">{</span> Fragment <span class=\"token punctuation\">}</span> <span class=\"token keyword\">from</span> <span class=\"token string\">'react'</span>\n<span class=\"token keyword\">import</span> <span class=\"token punctuation\">{</span> Field<span class=\"token punctuation\">,</span> ErrorMessage <span class=\"token punctuation\">}</span> <span class=\"token keyword\">from</span> <span class=\"token string\">'formik'</span>\n<span class=\"token keyword\">import</span> <span class=\"token punctuation\">{</span> <span class=\"token constant\">FIRST_NAME</span><span class=\"token punctuation\">,</span> <span class=\"token constant\">LAST_NAME</span><span class=\"token punctuation\">,</span> <span class=\"token constant\">EMAIL</span><span class=\"token punctuation\">,</span> <span class=\"token constant\">PASSWORD</span> <span class=\"token punctuation\">}</span> <span class=\"token keyword\">from</span> <span class=\"token string\">'./fieldsNames'</span>\n\n<span class=\"token keyword\">export</span> <span class=\"token keyword\">default</span> <span class=\"token keyword\">class</span> <span class=\"token class-name\">NewUserSubForm</span> <span class=\"token keyword\">extends</span> <span class=\"token class-name\">React<span class=\"token punctuation\">.</span>Component</span> <span class=\"token punctuation\">{</span>\n  <span class=\"token function\">render</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n    <span class=\"token keyword\">return</span> <span class=\"token punctuation\">(</span>\n      <span class=\"token operator\">&lt;</span>Fragment<span class=\"token operator\">></span>\n        <span class=\"token operator\">&lt;</span>Field component<span class=\"token operator\">=</span><span class=\"token string\">\"input\"</span> name<span class=\"token operator\">=</span><span class=\"token punctuation\">{</span><span class=\"token constant\">FIRST_NAME</span><span class=\"token punctuation\">}</span> <span class=\"token operator\">/</span><span class=\"token operator\">></span>\n        <span class=\"token operator\">&lt;</span>ErrorMessage name<span class=\"token operator\">=</span><span class=\"token punctuation\">{</span><span class=\"token constant\">FIRST_NAME</span><span class=\"token punctuation\">}</span> <span class=\"token operator\">/</span><span class=\"token operator\">></span>\n        <span class=\"token operator\">&lt;</span>Field component<span class=\"token operator\">=</span><span class=\"token string\">\"input\"</span> name<span class=\"token operator\">=</span><span class=\"token punctuation\">{</span><span class=\"token constant\">LAST_NAME</span><span class=\"token punctuation\">}</span> <span class=\"token operator\">/</span><span class=\"token operator\">></span>\n        <span class=\"token operator\">&lt;</span>ErrorMessage name<span class=\"token operator\">=</span><span class=\"token punctuation\">{</span><span class=\"token constant\">LAST_NAME</span><span class=\"token punctuation\">}</span> <span class=\"token operator\">/</span><span class=\"token operator\">></span>\n        <span class=\"token operator\">&lt;</span>Field component<span class=\"token operator\">=</span><span class=\"token string\">\"input\"</span> name<span class=\"token operator\">=</span><span class=\"token punctuation\">{</span><span class=\"token constant\">EMAIL</span><span class=\"token punctuation\">}</span> <span class=\"token operator\">/</span><span class=\"token operator\">></span>\n        <span class=\"token operator\">&lt;</span>ErrorMessage name<span class=\"token operator\">=</span><span class=\"token punctuation\">{</span><span class=\"token constant\">EMAIL</span><span class=\"token punctuation\">}</span> <span class=\"token operator\">/</span><span class=\"token operator\">></span>\n        <span class=\"token operator\">&lt;</span>Field component<span class=\"token operator\">=</span><span class=\"token string\">\"input\"</span> name<span class=\"token operator\">=</span><span class=\"token punctuation\">{</span><span class=\"token constant\">PASSWORD</span><span class=\"token punctuation\">}</span> <span class=\"token operator\">/</span><span class=\"token operator\">></span>\n        <span class=\"token operator\">&lt;</span>ErrorMessage name<span class=\"token operator\">=</span><span class=\"token punctuation\">{</span><span class=\"token constant\">PASSWORD</span><span class=\"token punctuation\">}</span> <span class=\"token operator\">/</span><span class=\"token operator\">></span>\n      <span class=\"token operator\">&lt;</span><span class=\"token operator\">/</span>Fragment<span class=\"token operator\">></span>\n    <span class=\"token punctuation\">)</span>\n  <span class=\"token punctuation\">}</span>\n<span class=\"token punctuation\">}</span></code></pre></div>\n<p>And that’s it. In this phase we can test every single part of our subform: validation, the default values schema and the React component.</p>\n<p><strong>A piece of advice</strong>: Formik sets the fields’ values in its state using the <code class=\"language-text\">name</code> property, but the cool thing is that it uses it like the Lodash <code class=\"language-text\">set</code> function. It means that we can write the name of a field like this: <code class=\"language-text\">user.firstName</code>. In this way Formik will create an object in its state called <code class=\"language-text\">user</code>, and then a property inside of <code class=\"language-text\">user</code> called <code class=\"language-text\">firstName</code> that will contain the value of our field.</p>\n<p>This mechanism gives us power to improve the flexibility of our subform. How?</p>\n<h3>Making a subform flexible</h3>\n<p>Let’s edit our component in a way that it will accept an optional property called <code class=\"language-text\">namespace</code>. If received, the component will prepend the namespace to every field name. In this way it will be easier to wrap all the subform’s values under a certain object in the main form.</p>\n<div class=\"gatsby-highlight\" data-language=\"javascript\"><pre class=\"language-javascript\"><code class=\"language-javascript\"><span class=\"token comment\">//  UserSubform/index.js</span>\n<span class=\"token keyword\">import</span> React<span class=\"token punctuation\">,</span> <span class=\"token punctuation\">{</span> Fragment <span class=\"token punctuation\">}</span> <span class=\"token keyword\">from</span> <span class=\"token string\">'react'</span>\n<span class=\"token keyword\">import</span> PropTypes <span class=\"token keyword\">from</span> <span class=\"token string\">'prop-types'</span>\n<span class=\"token keyword\">import</span> <span class=\"token punctuation\">{</span> Field<span class=\"token punctuation\">,</span> ErrorMessage <span class=\"token punctuation\">}</span> <span class=\"token keyword\">from</span> <span class=\"token string\">'formik'</span>\n<span class=\"token keyword\">import</span> <span class=\"token punctuation\">{</span> <span class=\"token constant\">FIRST_NAME</span><span class=\"token punctuation\">,</span> <span class=\"token constant\">LAST_NAME</span><span class=\"token punctuation\">,</span> <span class=\"token constant\">EMAIL</span><span class=\"token punctuation\">,</span> <span class=\"token constant\">PASSWORD</span> <span class=\"token punctuation\">}</span> <span class=\"token keyword\">from</span> <span class=\"token string\">'./fieldsNames'</span>\n\n<span class=\"token keyword\">export</span> <span class=\"token keyword\">default</span> <span class=\"token keyword\">class</span> <span class=\"token class-name\">NewUserSubForm</span> <span class=\"token keyword\">extends</span> <span class=\"token class-name\">React<span class=\"token punctuation\">.</span>Component</span> <span class=\"token punctuation\">{</span>\n  <span class=\"token keyword\">static</span> propTypes <span class=\"token operator\">=</span> <span class=\"token punctuation\">{</span>\n    namespace<span class=\"token operator\">:</span> PropTypes<span class=\"token punctuation\">.</span>string<span class=\"token punctuation\">,</span>\n  <span class=\"token punctuation\">}</span>\n\n  <span class=\"token function\">withNamespace</span><span class=\"token punctuation\">(</span><span class=\"token parameter\">fieldName</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n    <span class=\"token keyword\">const</span> <span class=\"token punctuation\">{</span> namespace <span class=\"token punctuation\">}</span> <span class=\"token operator\">=</span> <span class=\"token keyword\">this</span><span class=\"token punctuation\">.</span>props\n\n    <span class=\"token keyword\">return</span> namespace <span class=\"token operator\">?</span> <span class=\"token template-string\"><span class=\"token template-punctuation string\">`</span><span class=\"token interpolation\"><span class=\"token interpolation-punctuation punctuation\">${</span>namespace<span class=\"token interpolation-punctuation punctuation\">}</span></span><span class=\"token string\">.</span><span class=\"token interpolation\"><span class=\"token interpolation-punctuation punctuation\">${</span>fieldName<span class=\"token interpolation-punctuation punctuation\">}</span></span><span class=\"token template-punctuation string\">`</span></span> <span class=\"token operator\">:</span> fieldName\n  <span class=\"token punctuation\">}</span>\n\n  <span class=\"token function\">render</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n    <span class=\"token keyword\">const</span> <span class=\"token punctuation\">{</span> withNamespace <span class=\"token punctuation\">}</span> <span class=\"token operator\">=</span> <span class=\"token keyword\">this</span>\n\n    <span class=\"token keyword\">return</span> <span class=\"token punctuation\">(</span>\n      <span class=\"token operator\">&lt;</span>Fragment<span class=\"token operator\">></span>\n        <span class=\"token operator\">&lt;</span>Field component<span class=\"token operator\">=</span><span class=\"token string\">\"input\"</span> name<span class=\"token operator\">=</span><span class=\"token punctuation\">{</span><span class=\"token function\">withNamespace</span><span class=\"token punctuation\">(</span><span class=\"token constant\">FIRST_NAME</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">}</span> <span class=\"token operator\">/</span><span class=\"token operator\">></span>\n        <span class=\"token operator\">&lt;</span>ErrorMessage name<span class=\"token operator\">=</span><span class=\"token punctuation\">{</span><span class=\"token function\">withNamespace</span><span class=\"token punctuation\">(</span><span class=\"token constant\">FIRST_NAME</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">}</span> <span class=\"token operator\">/</span><span class=\"token operator\">></span>\n        <span class=\"token operator\">&lt;</span>Field component<span class=\"token operator\">=</span><span class=\"token string\">\"input\"</span> name<span class=\"token operator\">=</span><span class=\"token punctuation\">{</span><span class=\"token function\">withNamespace</span><span class=\"token punctuation\">(</span><span class=\"token constant\">LAST_NAME</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">}</span> <span class=\"token operator\">/</span><span class=\"token operator\">></span>\n        <span class=\"token operator\">&lt;</span>ErrorMessage name<span class=\"token operator\">=</span><span class=\"token punctuation\">{</span><span class=\"token function\">withNamespace</span><span class=\"token punctuation\">(</span><span class=\"token constant\">FIRST_NAME</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">}</span> <span class=\"token operator\">/</span><span class=\"token operator\">></span>\n        <span class=\"token operator\">&lt;</span>Field component<span class=\"token operator\">=</span><span class=\"token string\">\"input\"</span> name<span class=\"token operator\">=</span><span class=\"token punctuation\">{</span><span class=\"token function\">withNamespace</span><span class=\"token punctuation\">(</span><span class=\"token constant\">EMAIL</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">}</span> <span class=\"token operator\">/</span><span class=\"token operator\">></span>\n        <span class=\"token operator\">&lt;</span>ErrorMessage name<span class=\"token operator\">=</span><span class=\"token punctuation\">{</span><span class=\"token function\">withNamespace</span><span class=\"token punctuation\">(</span><span class=\"token constant\">FIRST_NAME</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">}</span> <span class=\"token operator\">/</span><span class=\"token operator\">></span>\n        <span class=\"token operator\">&lt;</span>Field component<span class=\"token operator\">=</span><span class=\"token string\">\"input\"</span> name<span class=\"token operator\">=</span><span class=\"token punctuation\">{</span><span class=\"token function\">withNamespace</span><span class=\"token punctuation\">(</span><span class=\"token constant\">PASSWORD</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">}</span> <span class=\"token operator\">/</span><span class=\"token operator\">></span>\n        <span class=\"token operator\">&lt;</span>ErrorMessage name<span class=\"token operator\">=</span><span class=\"token punctuation\">{</span><span class=\"token function\">withNamespace</span><span class=\"token punctuation\">(</span><span class=\"token constant\">FIRST_NAME</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">}</span> <span class=\"token operator\">/</span><span class=\"token operator\">></span>\n      <span class=\"token operator\">&lt;</span><span class=\"token operator\">/</span>Fragment<span class=\"token operator\">></span>\n    <span class=\"token punctuation\">)</span>\n  <span class=\"token punctuation\">}</span>\n<span class=\"token punctuation\">}</span></code></pre></div>\n<p>We don’t need to do that with the other parts of the subform, the main form will be responsible for that. And, about the main form, let’s see how to implement it!</p>\n<h2>The main form</h2>\n<p>Finally, we’re going to create our main form component. Let’s define its responsibilities just like we did with our subform. The main form will be responsible for:</p>\n<ul>\n<li>Compose the validation</li>\n<li>Compose the React components</li>\n<li>Compose and eventually overwrite the default values</li>\n<li>Orchestrate all the above elements in the right way (if we add a namespace for a subform we should put its validation schema under the same namespace)</li>\n<li>Handle the submission of the form</li>\n<li>Handle the display logic of the server-side errors (and all the form level errors)</li>\n</ul>\n<p>It's a lot of responsibilities, <em>and that’s all right</em>. The main form represents a specific point in the UI/UX where the user needs to insert some data. In our case, it could be a registration form, but it could also be a registration combined with a purchase, just like when you buy something from amazon and you agree to sign up in the process.</p>\n<p>The point is: <strong>A Form is a unique component that represent a specific use case</strong>, so it has to be designed accordingly. That’s why it makes no sense to create a “god-form” component with hundreds of props that decides which endpoint the form is going to use. It just creates useless complexity.</p>\n<p>In my opinion, the best way to organize this approach is to create a folder where you’ll store all your subforms. Every subform will be represented by its directory and it will contain all its parts: validation, values, fields and the React component.\nA main form, instead, should be created ad-hoc to fit the needs of a certain use case, for example inside a certain route.</p>\n<p>So, with that in mind, let’s proceed to the implementation. We’ll have our directory called <code class=\"language-text\">registrationForm</code> and it will have the same parts of a subform:</p>\n<p>Fields Names</p>\n<div class=\"gatsby-highlight\" data-language=\"javascript\"><pre class=\"language-javascript\"><code class=\"language-javascript\"><span class=\"token comment\">//  CreateNewUserRoute/form/fieldsNames.js</span>\n<span class=\"token keyword\">export</span> <span class=\"token punctuation\">{</span> <span class=\"token constant\">FIRST_NAME</span><span class=\"token punctuation\">,</span> <span class=\"token constant\">LAST_NAME</span><span class=\"token punctuation\">,</span> <span class=\"token constant\">EMAIL</span><span class=\"token punctuation\">,</span> <span class=\"token constant\">PASSWORD</span> <span class=\"token punctuation\">}</span> <span class=\"token keyword\">from</span> <span class=\"token string\">'./subforms/NewUserSubForm/fieldsNames'</span>\n<span class=\"token keyword\">export</span> <span class=\"token keyword\">const</span> <span class=\"token constant\">USER</span> <span class=\"token operator\">=</span> <span class=\"token string\">'user'</span></code></pre></div>\n<p>Validation</p>\n<div class=\"gatsby-highlight\" data-language=\"javascript\"><pre class=\"language-javascript\"><code class=\"language-javascript\"><span class=\"token comment\">//  CreateNewUserRoute/form/validationSchema.js</span>\n<span class=\"token keyword\">import</span> <span class=\"token operator\">*</span> <span class=\"token keyword\">as</span> yup <span class=\"token keyword\">from</span> <span class=\"token string\">'yup'</span>\n<span class=\"token keyword\">import</span> <span class=\"token punctuation\">{</span> <span class=\"token constant\">USER</span> <span class=\"token punctuation\">}</span> <span class=\"token keyword\">from</span> <span class=\"token string\">'./fieldsNames'</span>\n<span class=\"token keyword\">import</span> userValidationSchema <span class=\"token keyword\">from</span> <span class=\"token string\">'./subforms/NewUserSubForm/validationSchema'</span>\n\n<span class=\"token keyword\">export</span> <span class=\"token keyword\">default</span> yup<span class=\"token punctuation\">.</span><span class=\"token function\">object</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">{</span>\n  <span class=\"token punctuation\">[</span><span class=\"token constant\">USER</span><span class=\"token punctuation\">]</span><span class=\"token operator\">:</span> userValidationSchema<span class=\"token punctuation\">,</span>\n<span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span></code></pre></div>\n<p>Default values</p>\n<div class=\"gatsby-highlight\" data-language=\"javascript\"><pre class=\"language-javascript\"><code class=\"language-javascript\"><span class=\"token comment\">//  CreateNewUserRoute/form/defaultValues.js</span>\n<span class=\"token keyword\">import</span> <span class=\"token punctuation\">{</span> <span class=\"token constant\">USER</span> <span class=\"token punctuation\">}</span> <span class=\"token keyword\">from</span> <span class=\"token string\">'./field Names'</span>\n<span class=\"token keyword\">import</span> userDefaultValues <span class=\"token keyword\">from</span> <span class=\"token string\">'./subforms/NewUserSubForm/defaultValues'</span>\n\n<span class=\"token keyword\">export</span> <span class=\"token keyword\">default</span> <span class=\"token punctuation\">{</span>\n  <span class=\"token punctuation\">[</span><span class=\"token constant\">USER</span><span class=\"token punctuation\">]</span><span class=\"token operator\">:</span> userDefaultValues<span class=\"token punctuation\">,</span>\n<span class=\"token punctuation\">}</span></code></pre></div>\n<p>The React component</p>\n<div class=\"gatsby-highlight\" data-language=\"javascript\"><pre class=\"language-javascript\"><code class=\"language-javascript\"><span class=\"token comment\">//  CreateNewUserRoute/form/index.js</span>\n<span class=\"token keyword\">import</span> React <span class=\"token keyword\">from</span> <span class=\"token string\">'react'</span>\n<span class=\"token keyword\">import</span> <span class=\"token punctuation\">{</span> Formik<span class=\"token punctuation\">,</span> Form <span class=\"token punctuation\">}</span> <span class=\"token keyword\">from</span> <span class=\"token string\">'formik'</span>\n<span class=\"token keyword\">import</span> NewUserSubForm <span class=\"token keyword\">from</span> <span class=\"token string\">'./subforms/NewUserSubForm'</span>\n<span class=\"token keyword\">import</span> validationSchema <span class=\"token keyword\">from</span> <span class=\"token string\">'./validationSchema'</span>\n<span class=\"token keyword\">import</span> defaultValues <span class=\"token keyword\">from</span> <span class=\"token string\">'./defaultValues'</span>\n<span class=\"token keyword\">import</span> <span class=\"token punctuation\">{</span> <span class=\"token constant\">USER</span> <span class=\"token punctuation\">}</span> <span class=\"token keyword\">from</span> <span class=\"token string\">'./fieldsNames'</span>\n<span class=\"token keyword\">import</span> ErrorBanner <span class=\"token keyword\">from</span> <span class=\"token string\">'path/to/components/ErrorBanner'</span>\n\n<span class=\"token keyword\">export</span> <span class=\"token keyword\">default</span> <span class=\"token keyword\">class</span> <span class=\"token class-name\">NewUserSubForm</span> <span class=\"token keyword\">extends</span> <span class=\"token class-name\">React<span class=\"token punctuation\">.</span>Component</span> <span class=\"token punctuation\">{</span>\n  state <span class=\"token operator\">=</span> <span class=\"token punctuation\">{</span>\n    unknownErrors<span class=\"token operator\">:</span> <span class=\"token keyword\">null</span><span class=\"token punctuation\">,</span>\n  <span class=\"token punctuation\">}</span>\n\n  <span class=\"token function-variable function\">onSubmit</span> <span class=\"token operator\">=</span> <span class=\"token keyword\">async</span> <span class=\"token punctuation\">(</span><span class=\"token parameter\">values<span class=\"token punctuation\">,</span> <span class=\"token punctuation\">{</span> setSubmitting<span class=\"token punctuation\">,</span> setErrors <span class=\"token punctuation\">}</span></span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">{</span>\n    <span class=\"token keyword\">try</span> <span class=\"token punctuation\">{</span>\n      <span class=\"token comment\">//  Send values somehow</span>\n      <span class=\"token keyword\">await</span> <span class=\"token function\">sendForm</span><span class=\"token punctuation\">(</span>values<span class=\"token punctuation\">)</span>\n    <span class=\"token punctuation\">}</span> <span class=\"token keyword\">catch</span> <span class=\"token punctuation\">(</span>e<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n      <span class=\"token comment\">//  Map and show the errors in your form</span>\n      <span class=\"token keyword\">const</span> <span class=\"token punctuation\">[</span>formErrors<span class=\"token punctuation\">,</span> unknownErrors<span class=\"token punctuation\">]</span> <span class=\"token operator\">=</span> <span class=\"token function\">mapErrorsFromRequest</span><span class=\"token punctuation\">(</span>e<span class=\"token punctuation\">)</span>\n\n      <span class=\"token function\">setErrors</span><span class=\"token punctuation\">(</span>formErrors<span class=\"token punctuation\">)</span>\n      <span class=\"token keyword\">this</span><span class=\"token punctuation\">.</span><span class=\"token function\">setState</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">{</span>\n        unknownErrors<span class=\"token punctuation\">,</span>\n      <span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span>\n    <span class=\"token punctuation\">}</span> <span class=\"token keyword\">finally</span> <span class=\"token punctuation\">{</span>\n      <span class=\"token function\">setSubmitting</span><span class=\"token punctuation\">(</span><span class=\"token boolean\">false</span><span class=\"token punctuation\">)</span>\n    <span class=\"token punctuation\">}</span>\n  <span class=\"token punctuation\">}</span>\n\n  <span class=\"token function\">render</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n    <span class=\"token keyword\">const</span> <span class=\"token punctuation\">{</span> unknownErrors <span class=\"token punctuation\">}</span> <span class=\"token operator\">=</span> <span class=\"token keyword\">this</span><span class=\"token punctuation\">.</span>state\n\n    <span class=\"token keyword\">return</span> <span class=\"token punctuation\">(</span>\n      <span class=\"token operator\">&lt;</span>Formik onSubmit<span class=\"token operator\">=</span><span class=\"token punctuation\">{</span><span class=\"token keyword\">this</span><span class=\"token punctuation\">.</span>onSubmit<span class=\"token punctuation\">}</span> initialValues<span class=\"token operator\">=</span><span class=\"token punctuation\">{</span>defaultValues<span class=\"token punctuation\">}</span> validationSchema<span class=\"token operator\">=</span><span class=\"token punctuation\">{</span>validationSchema<span class=\"token punctuation\">}</span><span class=\"token operator\">></span>\n        <span class=\"token punctuation\">{</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">(</span>\n          <span class=\"token operator\">&lt;</span>Form<span class=\"token operator\">></span>\n            <span class=\"token punctuation\">{</span>unknownErrors <span class=\"token operator\">&amp;&amp;</span> <span class=\"token operator\">&lt;</span>ErrorBanner errors<span class=\"token operator\">=</span><span class=\"token punctuation\">{</span>unknownErrors<span class=\"token punctuation\">}</span> <span class=\"token operator\">/</span><span class=\"token operator\">></span><span class=\"token punctuation\">}</span>\n            <span class=\"token operator\">&lt;</span>NewUserSubForm namespace<span class=\"token operator\">=</span><span class=\"token punctuation\">{</span><span class=\"token constant\">USER</span><span class=\"token punctuation\">}</span> <span class=\"token operator\">/</span><span class=\"token operator\">></span>\n          <span class=\"token operator\">&lt;</span><span class=\"token operator\">/</span>Form<span class=\"token operator\">></span>\n        <span class=\"token punctuation\">)</span><span class=\"token punctuation\">}</span>\n      <span class=\"token operator\">&lt;</span><span class=\"token operator\">/</span>Formik<span class=\"token operator\">></span>\n    <span class=\"token punctuation\">)</span>\n  <span class=\"token punctuation\">}</span>\n<span class=\"token punctuation\">}</span></code></pre></div>\n<p>And that’s it! Of course, this is a very simple example, you could have different needs.</p>\n<h2>Helpful advices on creating subforms</h2>\n<p>I want to leave you with some advices that helped me while I was refactoring my codebase. It's good to have them in mind to ease the process of code refactoring.</p>\n<h3>A subform should have only first level values in its state</h3>\n<p>A subform should have only first level values in its state, which means that, when you design a subform, you shouldn’t get crazy about the shape of its values. It should be a flat object and every key should contain the field value.\nThis way it’s so much easier to write validations, default values and error handling (and why not, also the React component).</p>\n<p>You can avoid this advice <strong>only when you are using a subform into you subform</strong>. For example, let’s say you have an address subform. It has a lot of fields and a complex validation schema. In that scenario all the logic will be handled by the address subform and you’ll just need to orchestrate it in your own subform, just like you would do in the main form.</p>\n<h3>Keep the validation schema extensible and scalable</h3>\n<p>I didn’t do it in this article but the idea is to export a function instead of a schema. This function will accept parameters that will define the schema that you’ll get.\nIn this case you can toggle the “required” validation in some cases, or other kinds of validation.</p>\n<p><strong>Example</strong>: let’s say that we want to make the “lastName” field optional, but not always. That’s how you could define your schema:</p>\n<div class=\"gatsby-highlight\" data-language=\"javascript\"><pre class=\"language-javascript\"><code class=\"language-javascript\"><span class=\"token comment\">//  UserSubform/validationSchema.js</span>\n<span class=\"token keyword\">import</span> <span class=\"token operator\">*</span> <span class=\"token keyword\">as</span> yup <span class=\"token keyword\">from</span> <span class=\"token string\">'yup'</span>\n<span class=\"token keyword\">import</span> <span class=\"token punctuation\">{</span> <span class=\"token constant\">FIRST_NAME</span><span class=\"token punctuation\">,</span> <span class=\"token constant\">LAST_NAME</span><span class=\"token punctuation\">,</span> <span class=\"token constant\">EMAIL</span><span class=\"token punctuation\">,</span> <span class=\"token constant\">PASSWORD</span> <span class=\"token punctuation\">}</span> <span class=\"token keyword\">from</span> <span class=\"token string\">'./fieldsNames'</span>\n\n<span class=\"token keyword\">const</span> <span class=\"token constant\">MIN_PASSWORD_LENGTH</span> <span class=\"token operator\">=</span> <span class=\"token number\">8</span>\n\n<span class=\"token keyword\">const</span> <span class=\"token constant\">REQUIRED_MESSAGE</span> <span class=\"token operator\">=</span> <span class=\"token string\">'This field is required'</span>\n<span class=\"token keyword\">const</span> <span class=\"token constant\">INVALID_EMAIL_FORMAT</span> <span class=\"token operator\">=</span> <span class=\"token string\">'Invalid email format'</span>\n<span class=\"token keyword\">const</span> <span class=\"token constant\">PASSWORD_TOO_SHOWRT</span> <span class=\"token operator\">=</span> <span class=\"token template-string\"><span class=\"token template-punctuation string\">`</span><span class=\"token string\">The password must be long at least </span><span class=\"token interpolation\"><span class=\"token interpolation-punctuation punctuation\">${</span><span class=\"token constant\">MIN_PASSWORD_LENGTH</span><span class=\"token interpolation-punctuation punctuation\">}</span></span><span class=\"token string\"> characters</span><span class=\"token template-punctuation string\">`</span></span>\n\n<span class=\"token keyword\">export</span> <span class=\"token keyword\">default</span> <span class=\"token keyword\">function</span> <span class=\"token function\">validationSchema</span><span class=\"token punctuation\">(</span><span class=\"token parameter\">mandatoryFields <span class=\"token operator\">=</span> <span class=\"token punctuation\">{</span> <span class=\"token punctuation\">[</span><span class=\"token constant\">LAST_NAME</span><span class=\"token punctuation\">]</span><span class=\"token operator\">:</span> <span class=\"token boolean\">true</span> <span class=\"token punctuation\">}</span></span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n  <span class=\"token keyword\">return</span> yup<span class=\"token punctuation\">.</span><span class=\"token function\">object</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">{</span>\n    <span class=\"token punctuation\">[</span><span class=\"token constant\">FIRST_NAME</span><span class=\"token punctuation\">]</span><span class=\"token operator\">:</span> yup<span class=\"token punctuation\">.</span><span class=\"token function\">string</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">required</span><span class=\"token punctuation\">(</span><span class=\"token constant\">REQUIRED_MESSAGE</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span>\n    <span class=\"token punctuation\">[</span><span class=\"token constant\">LAST_NAME</span><span class=\"token punctuation\">]</span><span class=\"token operator\">:</span> yup<span class=\"token punctuation\">.</span><span class=\"token function\">lazy</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">(</span>mandatoryFields<span class=\"token punctuation\">.</span>lastName <span class=\"token operator\">?</span> yup<span class=\"token punctuation\">.</span><span class=\"token function\">string</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">required</span><span class=\"token punctuation\">(</span><span class=\"token constant\">REQUIRED_MESSAGE</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">:</span> yup<span class=\"token punctuation\">.</span><span class=\"token function\">string</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span>\n    <span class=\"token punctuation\">[</span><span class=\"token constant\">EMAIL</span><span class=\"token punctuation\">]</span><span class=\"token operator\">:</span> yup\n      <span class=\"token punctuation\">.</span><span class=\"token function\">string</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span>\n      <span class=\"token punctuation\">.</span><span class=\"token function\">required</span><span class=\"token punctuation\">(</span><span class=\"token constant\">REQUIRED_MESSAGE</span><span class=\"token punctuation\">)</span>\n      <span class=\"token punctuation\">.</span><span class=\"token function\">email</span><span class=\"token punctuation\">(</span><span class=\"token constant\">INVALID_EMAIL_FORMAT</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span>\n    <span class=\"token punctuation\">[</span><span class=\"token constant\">PASSWORD</span><span class=\"token punctuation\">]</span><span class=\"token operator\">:</span> yup\n      <span class=\"token punctuation\">.</span><span class=\"token function\">string</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span>\n      <span class=\"token punctuation\">.</span><span class=\"token function\">required</span><span class=\"token punctuation\">(</span><span class=\"token constant\">REQUIRED_MESSAGE</span><span class=\"token punctuation\">)</span>\n      <span class=\"token punctuation\">.</span><span class=\"token function\">min</span><span class=\"token punctuation\">(</span><span class=\"token constant\">MIN_PASSWORD_LENGTH</span><span class=\"token punctuation\">,</span> <span class=\"token constant\">PASSWORD_TOO_SHOWRT</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span>\n  <span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span>\n<span class=\"token punctuation\">}</span></code></pre></div>\n<p>Now you have a scalable validation schema.\nIn this way you can always decide if a certain field is required or not. Also, you can extend that function to add parameters. In this way, if your subform scales, you’ll just need to add parameters and adjust the code in the subform accordingly, but <strong>every single form that uses your subform won’t be affected by these changes because everything is retro compatible</strong>.</p>\n<h2>Conclusions</h2>\n<p>Dealing with forms is not easy. Of course, there are simple cases, but there are also trickier ones. This was my way to organize the code, and of course, it’s not perfect.\nI’m sure there are other thousands amazing ways to solve this problem better than this, but for now, this is the best way I’ve found to keep everything testable, maintainable and scalable.</p>\n<p>I hope this will help you, and if you have a better approach, I’m looking forward to reading it!\nUntil next time, happy hacking!</p>","fields":{"slug":"/the-concept-of-subforms-with-formik/","tags":["formik","forms","react","subforms"]}}},{"node":{"id":"4847d312-706f-5678-9e9e-1a333f42095e","frontmatter":{"category":"Coding","title":"How we use ES6 generators to simplify our React Redux application code","date":"2019-04-04","summary":"How we use ES6 generators instead of thunk to simplify our React Redux application code and improve productivity","thumbnail":{"relativePath":"pages/es6-generators-react-redux/thumbnail.png","childImageSharp":{"resolutions":{"base64":"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAUCAYAAACNiR0NAAAACXBIWXMAAAnLAAAJywEjDYgKAAADmUlEQVQ4y3VV2W/MURQemUY7+7Szd2Y681umLSHWB4TW1nqo5YUisYVIVGsJEXtrryUIam9Va0nQ1hoULYrEFhL8ASS2+A94+Zxzfp0xpR5ucnPPud893znfOdekqioUWqqiyFI0DVooAN2bDTUagaLrYpdFez5jm5YbFF+5k8SgZUoHVFQCi4QRmlIOb8V65A0fAd2Xk7rA++iIMfAsq0Zu2XRo4dweoClAOaDXtYAPgTlLkNn6Cq5tx5HV+hLu6sMUVRRqLM84a3kB95Y6ZLa9RnDGAmhBP4HqBsP0CIUq0bCdvInQtNnIt5gRGzgIjgMXYD/SAvvRNjj3NSPefwAKMvsgMHuxnHMQDJiKUPmLsvVMOyKjxxtUiL4WCsL89BsyHn+WaNS8qPiHJ5bJ42o89ifHEmEyqXpCAOxHWxEZW4qEwyIAjsOXkb1uL7I37Ifj4EWJKGHPQrhkChyHLlEeQ1AS+amgTCm65Kj7veJkO3UL2RsPwNr0AKYPv2Bt7oDlXKexb7wn4Lb623DsPw/d4+7Oo9YdYTwu1fItXi0AfW++Q+a1t/Cs2i5Uo6PHIV7QD0pBISLFpTA/+w7Pyq3ix8t69j7886sk/xIh64oTb23qoAsliA0eRrm5IZF6K9ZRdWNw7m2Cc/cZ0SBLhqnbTtxAbNBQhCeUwXKxS+wsOZNv0SoyXpfQOeGsNeeeRmQ8/ER7j9Ay/YAsZ22DpMX85AtcO06SwHMMoZMfp8A/r5IAF66U1wSQohFAei2j86OxJ6kkAV27TgtgRtdn2teLXYLwM+Ad+OcuTaNMuYiOKibtDRY5sMa8S9bKBb7MEWmRXIMy+QvlIcNJEZNgucCUG6QWqaLwZcv5R1SQN9IF3sqNMHd9kUdEFrQiYyZQob7CW7VJ/Pre+iCF9C9Y/qcohiAN2bCI7ceukrjvwl1TJw+Y3v+EpblTpJPcuzcfEmkxC06BFvSlySZN2Fwle12rVDvhssnUsR+5IsLOWVNLthY5SzitiBRNlHY0JlLiL2EnW49esTa2i/ak9ciZRcsVZ6rcFQJANga0NtxNa9tk6/UYDiGiQsNh6izkZ5kRL+wH187TUiSWFlc/Xtgf+TQceNJwetK7pNfx5Z9TIeOLx1bWledw1dYbo4kk5dp5Ss7YxoULzFxk5E/vZXz1GLAUIcsjOrLI0Fo3JRmwVHXPihqEJpf/f8D+9wsg8H++ADqTgRDq/Qv4DWMLuHUxNoXrAAAAAElFTkSuQmCC","width":325,"height":325,"src":"/static/2bee11a830bacc5ae9006df56b20c33a/b3029/thumbnail.png","srcSet":"/static/2bee11a830bacc5ae9006df56b20c33a/b3029/thumbnail.png 1x,\n/static/2bee11a830bacc5ae9006df56b20c33a/8d141/thumbnail.png 1.5x,\n/static/2bee11a830bacc5ae9006df56b20c33a/ee72c/thumbnail.png 2x,\n/static/2bee11a830bacc5ae9006df56b20c33a/5dfa8/thumbnail.png 3x"}}},"authorName":"Chirag Swadia","authorDescription":"Chirag is a Software Engineer at AUTO1 Group.","authorAvatar":{"relativePath":"pages/es6-generators-react-redux/avatar.jpg","childImageSharp":{"resolutions":{"base64":"data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAAUABQDASIAAhEBAxEB/8QAGAABAAMBAAAAAAAAAAAAAAAAAAECAwT/xAAXAQEBAQEAAAAAAAAAAAAAAAAEAwAB/9oADAMBAAIQAxAAAAGIveV5aObk0FjsCs//xAAbEAADAAIDAAAAAAAAAAAAAAAAAQIRIRIiQf/aAAgBAQABBQKnxmHTMGhGz0l9f//EABoRAAICAwAAAAAAAAAAAAAAAAABAhAxMkH/2gAIAQMBAT8B7U9mLB//xAAZEQABBQAAAAAAAAAAAAAAAAAAAQIQMTL/2gAIAQIBAT8BhuRbP//EABsQAAIBBQAAAAAAAAAAAAAAAAARAgEQIDFB/9oACAEBAAY/AmKcEatzCh//xAAbEAEAAwADAQAAAAAAAAAAAAABABEhMVFh8P/aAAgBAQABPyEnrfkRsPknmGxTsy8Dqp82W0JRuRFFn//aAAwDAQACAAMAAAAQ+Dj/AP/EABgRAAMBAQAAAAAAAAAAAAAAAAABETEQ/9oACAEDAQE/EG5ovBkf/8QAGBEAAgMAAAAAAAAAAAAAAAAAADEQESH/2gAIAQIBAT8Q2lCBh//EABwQAQADAQEAAwAAAAAAAAAAAAEAESExUXGB8P/aAAgBAQABPxCyt4AerkU0XY8TkPRXxBSQfql1NpWO/co8qKgOPZRgcYmBU9n/2Q==","width":50,"height":50,"src":"/static/8cf5c37636309895b29dd7ce5f1fcf28/d2d31/avatar.jpg","srcSet":"/static/8cf5c37636309895b29dd7ce5f1fcf28/d2d31/avatar.jpg 1x,\n/static/8cf5c37636309895b29dd7ce5f1fcf28/0b804/avatar.jpg 1.5x,\n/static/8cf5c37636309895b29dd7ce5f1fcf28/753c3/avatar.jpg 2x,\n/static/8cf5c37636309895b29dd7ce5f1fcf28/31ca8/avatar.jpg 3x"}}},"headerImage":{"relativePath":"pages/es6-generators-react-redux/headerImage.png","childImageSharp":{"resolutions":{"base64":"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAGCAYAAADDl76dAAAACXBIWXMAAAsSAAALEgHS3X78AAABWUlEQVQY022QS0/CQBSFOzMtFLCdtsOrPOQRIPJogIILgkY0GqKJG5cu3GqMxIULExOJG/9s/0N7nBbjRiaZnJs7ky/nHEWRx63WRDqVCjRdR344DUV/jPxohlQmC0YpNE2Dqqp/SqkC+8BFuzBHTucRYzSK3xzHOY95SrXXF1KCbK2Fzv1T6L1+ofewQa7egtz/u0Sh6BZO0HBmOLT9SO4iohAYhrED6ooidJMHldUNvJdt6G22Uj/hXtyiO/TgTyeY+j4WiwUKpTxEtomheyVhE4wq64jr5RgKi/86LJZdQQkJ7MEUg8f3cPz2jeHzB+zRHLIKcM5hmqZUE2ktg4bto1NYomZ56BVPo6Yzjwgh8Z8d0G22BZGRWTaH8vIyrK/vUDm7hpoz9kauWqMk8lFphZY4jspGL3HIubUD5oUQjKlB0o+qhokythf21yOhiVLCkg7jOXb4A0fehWKiiDXIAAAAAElFTkSuQmCC","width":757,"height":236,"src":"/static/c49511e796013b6394df522c11a4a9fc/7eaf7/headerImage.png","srcSet":"/static/c49511e796013b6394df522c11a4a9fc/7eaf7/headerImage.png 1x"}}}},"html":"<h2>Background</h2>\n<p>When I first started working on React/Redux, the very first choice of library I used for handling asynchronous actions was <a href=\"https://github.com/reduxjs/redux-thunk\">Redux Thunk</a> as its maintained by the authors of Redux, and is very popular as well. Consider the following example, where an action type is being created for incrementing a counter and a corresponding action creator for it.</p>\n<div class=\"gatsby-highlight\" data-language=\"javascript\"><pre class=\"language-javascript\"><code class=\"language-javascript\"><span class=\"token keyword\">const</span> <span class=\"token constant\">INCREMENT_COUNTER</span> <span class=\"token operator\">=</span> <span class=\"token string\">'INCREMENT_COUNTER'</span><span class=\"token punctuation\">;</span>\n\n<span class=\"token keyword\">const</span> <span class=\"token function-variable function\">increment</span> <span class=\"token operator\">=</span> <span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">(</span><span class=\"token punctuation\">{</span>\n  type<span class=\"token operator\">:</span> <span class=\"token constant\">INCREMENT_COUNTER</span>\n<span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span></code></pre></div>\n<p>Using redux thunk, an async action creator can be created as follows</p>\n<div class=\"gatsby-highlight\" data-language=\"javascript\"><pre class=\"language-javascript\"><code class=\"language-javascript\"><span class=\"token keyword\">const</span> <span class=\"token function-variable function\">incrementAsync</span> <span class=\"token operator\">=</span> <span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">{</span>\n  <span class=\"token keyword\">return</span> <span class=\"token parameter\">dispatch</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">{</span>\n    <span class=\"token function\">setTimeout</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">{</span>\n      <span class=\"token function\">dispatch</span><span class=\"token punctuation\">(</span><span class=\"token function\">increment</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n    <span class=\"token punctuation\">}</span><span class=\"token punctuation\">,</span> <span class=\"token number\">1000</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n  <span class=\"token punctuation\">}</span><span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">}</span></code></pre></div>\n<p>Pretty simple till now.</p>\n<h2>The Problem</h2>\n<p>Redux Thunk is easy to understand, but the problem arises when the application scales, and as the need for dispatching condition-based actions grows with the application, it leads to unmaintainable code. For example, consider the below code</p>\n<div class=\"gatsby-highlight\" data-language=\"javascript\"><pre class=\"language-javascript\"><code class=\"language-javascript\"><span class=\"token keyword\">const</span> <span class=\"token function-variable function\">makeSandwichesForEverybody</span> <span class=\"token operator\">=</span> <span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">(</span><span class=\"token parameter\">dispatch<span class=\"token punctuation\">,</span> getState</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">{</span>\n  <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span><span class=\"token operator\">!</span><span class=\"token function\">getState</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span>sandwiches<span class=\"token punctuation\">.</span>isShopOpen<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n    <span class=\"token keyword\">return</span> Promise<span class=\"token punctuation\">.</span><span class=\"token function\">resolve</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n  <span class=\"token punctuation\">}</span>\n\n  <span class=\"token keyword\">return</span> <span class=\"token function\">dispatch</span><span class=\"token punctuation\">(</span>\n    <span class=\"token function\">makeASandwichWithSecretSauce</span><span class=\"token punctuation\">(</span><span class=\"token string\">'My Grandma'</span><span class=\"token punctuation\">)</span>\n  <span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">then</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span>\n    Promise<span class=\"token punctuation\">.</span><span class=\"token function\">all</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">[</span>\n      <span class=\"token function\">dispatch</span><span class=\"token punctuation\">(</span><span class=\"token function\">makeASandwichWithSecretSauce</span><span class=\"token punctuation\">(</span><span class=\"token string\">'Me'</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span>\n      <span class=\"token function\">dispatch</span><span class=\"token punctuation\">(</span><span class=\"token function\">makeASandwichWithSecretSauce</span><span class=\"token punctuation\">(</span><span class=\"token string\">'My wife'</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span>\n    <span class=\"token punctuation\">]</span><span class=\"token punctuation\">)</span>\n  <span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">then</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span>\n    <span class=\"token function\">dispatch</span><span class=\"token punctuation\">(</span><span class=\"token function\">makeASandwichWithSecretSauce</span><span class=\"token punctuation\">(</span><span class=\"token string\">'Our kids'</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span>\n  <span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">then</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span>\n    <span class=\"token function\">dispatch</span><span class=\"token punctuation\">(</span><span class=\"token function\">getState</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span>myMoney <span class=\"token operator\">></span> <span class=\"token number\">42</span> <span class=\"token operator\">?</span>\n      <span class=\"token function\">withdrawMoney</span><span class=\"token punctuation\">(</span><span class=\"token number\">42</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">:</span>\n      <span class=\"token function\">apologize</span><span class=\"token punctuation\">(</span><span class=\"token string\">'Me'</span><span class=\"token punctuation\">,</span> <span class=\"token string\">'The Sandwich Shop'</span><span class=\"token punctuation\">)</span>\n    <span class=\"token punctuation\">)</span>\n  <span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">}</span><span class=\"token punctuation\">;</span></code></pre></div>\n<p>In the above code, there are too many callbacks and the code does not look clean. Also, it would become complex if more conditions are added to it later on. Then, how to simplify this?</p>\n<h2>ES6 Generators to the rescue</h2>\n<p>For our customer-facing websites like <a href=\"https://wirkaufendeinauto.de/auto-kaufen/\">wirkaufendeinauto</a> and <a href=\"https://www.autohero.com/de/\">AutoHero</a>, we are neither using Redux Thunk nor Redux Saga. Rather, we are using a very simple and lightweight npm module <a href=\"https://www.npmjs.com/package/redux-action-generators\">Redux Actions Generators</a> developed by our very own <a href=\"https://github.com/Tuch\">Alexander Afonin</a>, who works as a Senior Software Engineer at Auto1.\nIf this module is configured as a middleware in the React application, the above code can be simplified as shown below</p>\n<div class=\"gatsby-highlight\" data-language=\"javascript\"><pre class=\"language-javascript\"><code class=\"language-javascript\"><span class=\"token keyword\">const</span> <span class=\"token function-variable function\">makeSandwichesForEverybody</span> <span class=\"token operator\">=</span> <span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token keyword\">function</span><span class=\"token operator\">*</span> <span class=\"token punctuation\">(</span><span class=\"token punctuation\">{</span> getState <span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n  <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span><span class=\"token operator\">!</span><span class=\"token function\">getState</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span>sandwiches<span class=\"token punctuation\">.</span>isShopOpen<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n    <span class=\"token keyword\">return</span><span class=\"token punctuation\">;</span>\n  <span class=\"token punctuation\">}</span>\n\n  <span class=\"token keyword\">yield</span> <span class=\"token function\">makeASandwichWithSecretSauce</span><span class=\"token punctuation\">(</span><span class=\"token string\">'My Grandma'</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n  <span class=\"token keyword\">yield</span> <span class=\"token punctuation\">[</span><span class=\"token function\">makeASandwichWithSecretSauce</span><span class=\"token punctuation\">(</span><span class=\"token string\">'Me'</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span> <span class=\"token function\">makeASandwichWithSecretSauce</span><span class=\"token punctuation\">(</span><span class=\"token string\">'My wife'</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">;</span>\n  <span class=\"token keyword\">yield</span> <span class=\"token function\">makeASandwichWithSecretSauce</span><span class=\"token punctuation\">(</span><span class=\"token string\">'Our kids'</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n\n  <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span><span class=\"token function\">getState</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span>myMoney <span class=\"token operator\">></span> <span class=\"token number\">42</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n    <span class=\"token keyword\">yield</span> <span class=\"token function\">withdrawMoney</span><span class=\"token punctuation\">(</span><span class=\"token number\">42</span><span class=\"token punctuation\">)</span><span class=\"token operator\">:</span>\n  <span class=\"token punctuation\">}</span> <span class=\"token keyword\">else</span> <span class=\"token punctuation\">{</span>\n    <span class=\"token keyword\">yield</span> <span class=\"token function\">apologize</span><span class=\"token punctuation\">(</span><span class=\"token string\">'Me'</span><span class=\"token punctuation\">,</span> <span class=\"token string\">'The Sandwich Shop'</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n  <span class=\"token punctuation\">}</span>\n<span class=\"token punctuation\">}</span><span class=\"token punctuation\">;</span></code></pre></div>\n<p>Now you are ready to tackle the growing complexity with ease. Also, the code is clean and readable.</p>\n<p>One question that might arise is that why not use async/await with thunk actions which could have solved the problem that is being discussed earlier. But, there are advantages of using generators instead of async/await thunks which are listed below - </p>\n<h3>Testability</h3>\n<p>Redux Thunk returns promises, which are more difficult to test. Testing thunks often require complex mocking of the fetch API, Axios requests, or other functions. With generators, you do not need to mock functions wrapped with effects. This makes tests clean, readable and easier to write.</p>\n<h3>Error Handling</h3>\n<p>The best part about the Redux Actions Generator module is that you can catch all errors at one place, without the need to write multiple try catch blocks in different actions ( you can if you want to, but not mandatory ) With redux-thunk, this is not possible and you have to write error handlers everywhere, which makes the code look less readable.\nTo use this common error catching functionality, you can configure it while creating the store as shown below -</p>\n<div class=\"gatsby-highlight\" data-language=\"javascript\"><pre class=\"language-javascript\"><code class=\"language-javascript\"><span class=\"token keyword\">const</span> <span class=\"token function-variable function\">catchError</span> <span class=\"token operator\">=</span> <span class=\"token parameter\">error</span> <span class=\"token operator\">=></span> console<span class=\"token punctuation\">.</span><span class=\"token function\">error</span><span class=\"token punctuation\">(</span>error<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> \n<span class=\"token keyword\">const</span> middlewares <span class=\"token operator\">=</span> <span class=\"token function\">applyMiddleware</span><span class=\"token punctuation\">(</span><span class=\"token function\">createGeneratorMiddleware</span><span class=\"token punctuation\">(</span><span class=\"token keyword\">null</span><span class=\"token punctuation\">,</span> catchError<span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></code></pre></div>\n<p>Once you do this, your actions can become clean and more readable. For example, the below code...</p>\n<div class=\"gatsby-highlight\" data-language=\"javascript\"><pre class=\"language-javascript\"><code class=\"language-javascript\"><span class=\"token keyword\">const</span> <span class=\"token function-variable function\">someAction</span> <span class=\"token operator\">=</span> <span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token keyword\">function</span><span class=\"token operator\">*</span> <span class=\"token punctuation\">(</span><span class=\"token punctuation\">{</span> api <span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n  <span class=\"token keyword\">try</span> <span class=\"token punctuation\">{</span>\n    <span class=\"token keyword\">yield</span> api<span class=\"token punctuation\">.</span><span class=\"token function\">loadSomeItems</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n  <span class=\"token punctuation\">}</span> <span class=\"token keyword\">catch</span> <span class=\"token punctuation\">(</span>error<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n    <span class=\"token comment\">// handle error logic</span>\n    console<span class=\"token punctuation\">.</span><span class=\"token function\">log</span><span class=\"token punctuation\">(</span>error<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n  <span class=\"token punctuation\">}</span>\n<span class=\"token punctuation\">}</span></code></pre></div>\n<p>can be replaced with...</p>\n<div class=\"gatsby-highlight\" data-language=\"javascript\"><pre class=\"language-javascript\"><code class=\"language-javascript\"><span class=\"token keyword\">const</span> <span class=\"token function-variable function\">someAction</span> <span class=\"token operator\">=</span> <span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token keyword\">function</span><span class=\"token operator\">*</span> <span class=\"token punctuation\">(</span><span class=\"token punctuation\">{</span> api <span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n  <span class=\"token keyword\">yield</span> api<span class=\"token punctuation\">.</span><span class=\"token function\">loadSomeItems</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">}</span></code></pre></div>\n<p>In this way, all the uncaught errors will be caught with the <code class=\"language-text\">catchError</code> function.</p>\n<h2>Enough of Making Sandwiches</h2>\n<p>Let's get to some real life example on how we use this pattern in our code. Consider the <a href=\"https://wirkaufendeinauto.de/auto-kaufen/\">Auto Kaufen page</a> on our wirkaufendeinauto website where we show a list of ads, filters, header, footer and some other content.</p>\n<p>For this module, we have some actions like</p>\n<div class=\"gatsby-highlight\" data-language=\"javascript\"><pre class=\"language-javascript\"><code class=\"language-javascript\"><span class=\"token keyword\">const</span> <span class=\"token function-variable function\">loadAds</span> <span class=\"token operator\">=</span> <span class=\"token punctuation\">(</span><span class=\"token parameter\">filters</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span>\n  <span class=\"token keyword\">function</span><span class=\"token operator\">*</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n    <span class=\"token comment\">// filter is an object with some information like {make: 'Audi', model: 'A3'}</span>\n    \n    <span class=\"token keyword\">const</span> <span class=\"token punctuation\">{</span> ads<span class=\"token operator\">:</span> result <span class=\"token punctuation\">}</span> <span class=\"token operator\">=</span> <span class=\"token keyword\">yield</span> api<span class=\"token punctuation\">.</span><span class=\"token function\">findAds</span><span class=\"token punctuation\">(</span>filters<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n\n    <span class=\"token comment\">// Once we get the ads list, we just save it in the redux store</span>\n  <span class=\"token punctuation\">}</span>\n\n<span class=\"token keyword\">const</span> <span class=\"token function-variable function\">loadSimilarAds</span> <span class=\"token operator\">=</span> <span class=\"token punctuation\">(</span><span class=\"token parameter\">filters</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span>\n  <span class=\"token keyword\">function</span><span class=\"token operator\">*</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">{</span>\n      <span class=\"token comment\">//  this is same as loadAds, but the API endpoint from which it fetches data is different</span>\n  <span class=\"token punctuation\">}</span></code></pre></div>\n<p>Similarly, we have other actions like <code class=\"language-text\">loadDataFromCms</code>, <code class=\"language-text\">trackGtmEvents</code> etc. Now the action which will be called when the main component mounts, will be as shown below</p>\n<div class=\"gatsby-highlight\" data-language=\"javascript\"><pre class=\"language-javascript\"><code class=\"language-javascript\"><span class=\"token keyword\">export</span> <span class=\"token keyword\">const</span> <span class=\"token function-variable function\">loadPage</span> <span class=\"token operator\">=</span> <span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> \n  <span class=\"token keyword\">function</span><span class=\"token operator\">*</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">{</span> getState <span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">{</span>\n      <span class=\"token keyword\">yield</span> <span class=\"token function\">loadDataFromCms</span><span class=\"token punctuation\">(</span><span class=\"token string\">'header'</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n\n      <span class=\"token keyword\">const</span> filters <span class=\"token operator\">=</span> <span class=\"token keyword\">yield</span> <span class=\"token function\">getFiltersFromStore</span><span class=\"token punctuation\">(</span><span class=\"token function\">getState</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n      <span class=\"token keyword\">yield</span> <span class=\"token punctuation\">[</span>\n        <span class=\"token function\">loadAds</span><span class=\"token punctuation\">(</span>filters<span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span>\n        <span class=\"token function\">loadMakeModelSubtype</span><span class=\"token punctuation\">(</span>filters<span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span>\n        <span class=\"token function\">loadDataFromCms</span><span class=\"token punctuation\">(</span><span class=\"token string\">'home'</span><span class=\"token punctuation\">)</span>\n      <span class=\"token punctuation\">]</span><span class=\"token punctuation\">;</span>\n\n      <span class=\"token comment\">// If no ads found, we try to find similar ads which might interest the user</span>\n      <span class=\"token keyword\">if</span><span class=\"token punctuation\">(</span> <span class=\"token function\">getState</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span>ads<span class=\"token punctuation\">.</span>length <span class=\"token operator\">===</span> <span class=\"token number\">0</span> <span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n          <span class=\"token keyword\">yield</span> <span class=\"token function\">loadSimilarAds</span><span class=\"token punctuation\">(</span>filters<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n      <span class=\"token punctuation\">}</span>\n  <span class=\"token punctuation\">}</span></code></pre></div>\n<p>As you can see, in the above code we are making multiple API calls, some are in parallel, and some are fired conditionally based on the results of the previous API calls. This way our redux actions look clean and are easy to debug and maintain.</p>\n<h2>Summary</h2>\n<p>So this is how you can make use of the ES6 generators to simplify your React application code. Comments and suggestions are welcome.</p>","fields":{"slug":"/es6-generators-react-redux/","tags":["auto1","engineering","react","redux"]}}},{"node":{"id":"7cae20df-634c-53fc-9b57-d14a4a98b03e","frontmatter":{"category":"Social","title":"Embeddable Lightweight React Widgets","date":"2018-12-11","summary":"This article will introduce two approaches to integrate lightweight react apps (we will call them widgets) that can be embedded in any project","thumbnail":{"relativePath":"pages/embeddable-leightweight-react-widgets/thumbnail.png","childImageSharp":{"resolutions":{"base64":"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAQCAYAAAAWGF8bAAAACXBIWXMAABYlAAAWJQFJUiTwAAACDElEQVQ4y6WSa0tUURSG92+q6GL3soIypA+FRQbWkLcZtbxEQmpoF7MUoYxKbIgmJYmSoiDDz/2EOmdGZ+aM5khfDwNJ+2nts3Ps4uSBPjyss9c+e6137XerVCpFMpnExP9hpYYKfcgcCIEylUPhuqFQ6XSa9ZgzZL1QKM/zKEk2S8bL8TWX4Xu8l+XhFpbvtq1BaxHlisxSmBE+J1Pkk5+gsxIim6BhO9RuhfObLbVboH4b1FnUeka4s3MszTpw9RS6aQ/6Qjn60lF01wnL5Up0y37JHwhQKdehJI6DK0WXjMKeKnRsN0R3wmAjTA5b7rVZ1dKI5n3icu4LReYNixZZp3ILOAt58tm0LVhfBt1V8OQaTCfgwzgk+qH3NJhmolQVJoYojA9i4x0KT29RSAys5hK3+TYzKYeq0UaJjIgYxNs4vIvbgp3HoGmvLRhcqOlcJxfdLMmhKPRV24s2Bc5tgJF29PUaaJRxo7usorFuoQf6I5LfsTqyvngQ3XoILQvddwY98xz9bADdcYRgLyZGjF5B36hBS7HAFLPXUYFuPywGVfw0pTxABSoMRmVMut88C13HrULTObIR7neIyyftt8mtPJMgymQNZUWU/+Yx/mshiGP4rx7iTz2ya8PUKP7H9/jTE/gvRuz+n7x8YJFv5YqbvyEOB/yay3i43vzf+TX49zss4hLuP4cfa1IV+zKNxLYAAAAASUVORK5CYII=","width":402,"height":325,"src":"/static/dd3ba552f348daf0d9beb74158081069/b3029/thumbnail.png","srcSet":"/static/dd3ba552f348daf0d9beb74158081069/b3029/thumbnail.png 1x,\n/static/dd3ba552f348daf0d9beb74158081069/8d141/thumbnail.png 1.5x,\n/static/dd3ba552f348daf0d9beb74158081069/ee72c/thumbnail.png 2x,\n/static/dd3ba552f348daf0d9beb74158081069/5dfa8/thumbnail.png 3x"}}},"authorName":"Kareem Elbahrawy","authorDescription":"Kareem is Senior Frontend Engineer at AUTO1 Group","authorAvatar":{"relativePath":"pages/embeddable-leightweight-react-widgets/avatar.png","childImageSharp":{"resolutions":{"base64":"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAUCAYAAACNiR0NAAAACXBIWXMAAAsSAAALEgHS3X78AAAFRUlEQVQ4yyWUa1BUZRjHz8e+9MEP1SiWgrvsLrDAooBAYHIzHanwMpmZt3FMI8NMRSdzwEuYiAgusAu4BMsuuyzLXpDLAuH97piXvKIoCKiJWVYz9enXA334z3vOM+f83v/z/M97lJHBuwwN3Gbo0W2GB+7Q33d9/Pr50L1x/TooetzH6FAfL4b7+O3JA1G/6CEvRvoZHX7A6IjURu7zx9OHKAMPbvBs7MXHd3km6rt5iVtXz/P7037+fD7Av6+e8UQ2ePLwJk9l45dSH7p/nd8F+vfoY17JMy8F/lyMjW2o/HL1LCOPbomTu/LiLW5fPcfxrlbuXrvA0L3r+Jrq8DqPcPlUgJuXTnDj4ikunezmyukefhPXf78YFPAgf4n+eTmMcuPKaU71tjPcf2t89zvXL+Ky19PpaWbDmhW88fpraN6ZSKI+lB05qzgd8HHj0hm6fU0M3PmZZ2JiVDp8+ugmg/euoXS0NeNvsXOs08fJnlbavE5qzCZKiw+QFhvNR4mxLEpO4IM4A+kGHaX5ebjtNmpNldgsZurNRkyHSqg2llB16AcUU9l+qkr2UrF/F8Z9+VQW78ViLCYvdz3ZSXHs/HQh3y75kMK1y1gyK4Fl6Ql46spw1JRQX7EPl+UglQd3U7AjD2PRPpTCb3M5lP81Zbs2iTZTWrCJw3s3UZC7nIXJ8axMS+KbxfNZm5XGuqwMNn6cSYNxK+WFX2Dcu57yPespK5C1cBvmsp0oFpNR7B6ktlJU8b8ctZWYC3eS80EGOfNS2Zg9h1XpSXy3fDGm3BVYindTuGMzu/I2cKBgK3vyvmJzzjq25K5E8bmdHPU4ZXYOumSevZ0eLp/9iYC7QdpdwPcrl1C4aikHPl9G9ebVdFYXc+HsCY73tNMb8NPb7uZYhxdLZRkF2/NQGhstOB0WXM5aPG4rbT473R3NnJGA8pcvYuuCuez4JJtt2al4Du/m3IkAPRJgV0cL7f4mGo4Y6TraRG+Xl8BR1xiwFocAm1x1tHgaaPXZxKmL86e6KN6SI6A55I8FsyiDs946qffQJoB2kd/nwO+10d7qEEmXfieKzVYz7tApDt3uegLtzZwTWK2plKVpyXy3eK7McTar56ZRXr4fe3cLAXHj8drx+hplteGTrnxy7fM7UKwN5nGYSxwelWJFaRGLsubyfmoK2ZLylx9msnBOJu+npRMVE01mzmcYPRY5KYHx51sF1ioO/f5GWloaUH60lGOtM2G3mvFLEPPSZvPWhAmERYSTEh9HltzPiIlBowklIiyMMJ2W9xJm0GY1crLbTXvL/2PyiTweK0ptdRn1MthGq0AtFcTNiCE4VI1WFGaIRquPIDRchyZMh0EfSaRKjXryZPSTgsjYsobS0166PAJsscqJE6BVHNrrKmhqqKL6cBGRiTMJmTpVzu8UVHodoVGRaCIi0Ov1xEdGEz5NRXhIMOqgybxp0JNeV4S30yU/kR/xyOiUsdjra0ppqjdRU1mMPikBVdDb6KYINCpCFIVWgLHRMSREGdCrBBg8Fa1azdSQaQTNTyfPZaZDMnDZq6RlgVhrynAK0FpbQcKsJFQTJxGj1ZIYF0+YAPWi5Nh4kgzTiRJQuHQQqpqGSqfjLa2GlO3rcTlq8DRWozis1TilZbfNhE3CSU1NRT0xiDhpMTMpmZTYmURrw5muCyMx2oBBoxGHIWhkxqFSmxyiwvBxFs2eOvyNNShF+37AXGnGYaunylxOSmIyEcFqkmNiyUh6l9nxM8eD0MpMx0D6aSFEhISMh6bW6pgiQJV8p4eOlNAmM/wPrWQIzBh2TMkAAAAASUVORK5CYII=","width":50,"height":50,"src":"/static/ea2656d13f68652e7e988d1a80c98c8b/45876/avatar.png","srcSet":"/static/ea2656d13f68652e7e988d1a80c98c8b/45876/avatar.png 1x,\n/static/ea2656d13f68652e7e988d1a80c98c8b/eb85b/avatar.png 1.5x,\n/static/ea2656d13f68652e7e988d1a80c98c8b/4f71c/avatar.png 2x,\n/static/ea2656d13f68652e7e988d1a80c98c8b/9ec3e/avatar.png 3x"}}},"headerImage":{"relativePath":"pages/embeddable-leightweight-react-widgets/header.png","childImageSharp":{"resolutions":{"base64":"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAGCAYAAADDl76dAAAACXBIWXMAAAsSAAALEgHS3X78AAAA50lEQVQY032OsUvDQBTG+0e6OhYXFzcXXXQRxUEQpODgJIg4OImubiKiUoRCPC6X0FqSixbbhOQuP5ujOtRrP/h4D973/XgtZqrr2rlRWZbkee5cFIV3Npn5XqOWD6i1RgiBUoo4jpFSosKQKIoY9Pu8BwFJkiwHzh8n4zF6WsrS1DnJMvTXaDo/+Z7kXpj3w9/AIM14E5KeVM6i+4J4fSJ4fmQYhd7Ogg+t20fdBz7uLhne36BvL2BrBU63YXcVznZwCGsXf/gHtMbt9rqD2WtjTjYx+2tUh+tU5wdURxuYq+NZ/j/wB5xHx6fGez75AAAAAElFTkSuQmCC","width":1280,"height":420,"src":"/static/4786c8105880f38270b7cd8b2ee3faaf/26421/header.png","srcSet":"/static/4786c8105880f38270b7cd8b2ee3faaf/26421/header.png 1x,\n/static/4786c8105880f38270b7cd8b2ee3faaf/34a7a/header.png 1.5x,\n/static/4786c8105880f38270b7cd8b2ee3faaf/77cb2/header.png 2x"}}}},"html":"<p><em>\"We need to re-write EVERYTHING!\"</em>... It's understandable that a huge technical debt is created during the first period of building a company app, a lot of business needs, a lot of deadlines and smaller teams. And for webapps where a proper frontend solution was not considered, most of this technical debt falls on frontend and by time it becomes harder and harder to refactor till it reaches a point where the right way to refactor it is to re-write it. But that's not an option sometimes, isn't it?</p>\n<p>As an alternative, This article will introduce two approaches to integrate lightweight react apps (we will call them widgets) that can be embedded in any project.</p>\n<ul>\n<li>Traditional Approach</li>\n<li>Standalone Approach</li>\n</ul>\n<h2>React Widgets: Traditional Approach</h2>\n<p>React widgets implemented directly in your codebase.</p>\n<p>Create a similar folder structure to this:</p>\n<div class=\"gatsby-highlight\" data-language=\"text\"><pre class=\"language-text\"><code class=\"language-text\">.\n├── server\n    └── ....\n├── frontend\n    ├── widgets\n        ├── login.js\n        └── subscribe.js\n    └── components\n        ├── Login.js\n        ├── Subscribe.js\n        └── ....\n├── dist #ignored\n    ├── widget_login_bundle.js\n    └── widget_subscribe_bundle.js\n├── webpack.config.js\n└── package.json</code></pre></div>\n<p><code class=\"language-text\">/frontend/widgets</code> directory will contain entry points for all the widgets, each file inside should render a react app in a corresponding DOM element id</p>\n<p>For example <code class=\"language-text\">/frontend/widgets/login.js</code></p>\n<div class=\"gatsby-highlight\" data-language=\"javascript\"><pre class=\"language-javascript\"><code class=\"language-javascript\"><span class=\"token keyword\">import</span> React <span class=\"token keyword\">from</span> <span class=\"token string\">'react'</span><span class=\"token punctuation\">;</span>\n<span class=\"token keyword\">import</span> ReactDOM <span class=\"token keyword\">from</span> <span class=\"token string\">'react-dom'</span><span class=\"token punctuation\">;</span>\n<span class=\"token keyword\">import</span> Login <span class=\"token keyword\">from</span> <span class=\"token string\">'../components/Login'</span><span class=\"token punctuation\">;</span>\n\nReactDOM<span class=\"token punctuation\">.</span><span class=\"token function\">render</span><span class=\"token punctuation\">(</span>\n    <span class=\"token operator\">&lt;</span>Login <span class=\"token operator\">/</span><span class=\"token operator\">></span><span class=\"token punctuation\">,</span>\n    document<span class=\"token punctuation\">.</span><span class=\"token function\">getElementById</span><span class=\"token punctuation\">(</span><span class=\"token string\">'widget:login'</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span> <span class=\"token comment\">// &lt;-- NOTE the element id</span>\n<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></code></pre></div>\n<p><code class=\"language-text\">webpack.config.js</code> will look like this</p>\n<div class=\"gatsby-highlight\" data-language=\"javascript\"><pre class=\"language-javascript\"><code class=\"language-javascript\">module<span class=\"token punctuation\">.</span>exports <span class=\"token operator\">=</span> <span class=\"token punctuation\">{</span>\n    entry<span class=\"token operator\">:</span> <span class=\"token punctuation\">[</span>\n      <span class=\"token string\">'./frontend/widgets/login.js'</span><span class=\"token punctuation\">,</span>\n      <span class=\"token string\">'./frontend/widgets/subscribe.js'</span><span class=\"token punctuation\">,</span>\n    <span class=\"token punctuation\">]</span><span class=\"token punctuation\">,</span>\n    output<span class=\"token operator\">:</span> <span class=\"token punctuation\">{</span>\n        filename<span class=\"token operator\">:</span> <span class=\"token string\">'widget_[name]_bundle.js'</span><span class=\"token punctuation\">,</span>\n    <span class=\"token punctuation\">}</span>\n    <span class=\"token operator\">...</span>\n<span class=\"token punctuation\">}</span></code></pre></div>\n<p>Now running <code class=\"language-text\">webpack</code> from the project folder will create two bundle files <code class=\"language-text\">widget_login_bundle.js</code> and <code class=\"language-text\">widget_subscribe_bundle.js</code> in the <code class=\"language-text\">dist</code> folder.</p>\n<p>Now you can use a widget in one of your views like this</p>\n<div class=\"gatsby-highlight\" data-language=\"html\"><pre class=\"language-html\"><code class=\"language-html\">...\n<span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>div</span> <span class=\"token attr-name\">id</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span>widget:login<span class=\"token punctuation\">\"</span></span><span class=\"token punctuation\">></span></span><span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;/</span>div</span><span class=\"token punctuation\">></span></span>\n<span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>script</span> <span class=\"token attr-name\">defer</span> <span class=\"token attr-name\">src</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span>/dist/widget_login_bundle.js<span class=\"token punctuation\">\"</span></span> <span class=\"token punctuation\">/></span></span>\n...</code></pre></div>\n<h3>Pros</h3>\n<ul>\n<li>Easy to implement and straightforward.</li>\n<li>Doesn't need any further backend integration to make it work (except for SSR).</li>\n</ul>\n<h3>Cons</h3>\n<ul>\n<li>Depending on your backend, it might not be an easy task to server side render (SSR) widgets with this approach.</li>\n<li>You will need to configure your deployment process to run webpack.</li>\n<li>The frontend development and deployment processes are tightly coupled to the backend.</li>\n</ul>\n<hr>\n<h2>React Widgets: Standalone Approach</h2>\n<p>In this approach we will keep all frontend in a separate repository and have an npm script to generate an html and bundle js file for each widget and upload them to a CMS.</p>\n<p>But first, A new database model need to be introduced that will hold the widget data (name and html) and there should be a way to upload assets to a content server.</p>\n<p>For example you may expose two web service APIs similar to this:</p>\n<ul>\n<li>POST <code class=\"language-text\">example.com/api/widget/save-or-update</code> (Save or upload a widget entry in the database)</li>\n<li>POST <code class=\"language-text\">example.com/api/content-server/upload</code> (Upload an asset file to content server)</li>\n</ul>\n<p>The folder structure will be similar to the previous approach but this time in a separate repository:</p>\n<div class=\"gatsby-highlight\" data-language=\"text\"><pre class=\"language-text\"><code class=\"language-text\">.\n├── frontend # Same as before\n├── dist # Same as before\n└── scripts\n    ├── deployWidget.js\n    └── ....\n├── webpack.config.js\n└── package.json</code></pre></div>\n<p><code class=\"language-text\">/scripts/deployWidget.js</code> is a nodejs script that expects a <code class=\"language-text\">--widget</code> argument and will do the following:</p>\n<ul>\n<li>Upload this widget bundle file to a content server</li>\n<li>Create or update the widget entry html value in the database.</li>\n</ul>\n<div class=\"gatsby-highlight\" data-language=\"javascript\"><pre class=\"language-javascript\"><code class=\"language-javascript\"><span class=\"token keyword\">const</span> path <span class=\"token operator\">=</span> <span class=\"token function\">require</span><span class=\"token punctuation\">(</span><span class=\"token string\">'path'</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n<span class=\"token keyword\">const</span> argv <span class=\"token operator\">=</span> <span class=\"token function\">require</span><span class=\"token punctuation\">(</span><span class=\"token string\">'yargs'</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span>argv<span class=\"token punctuation\">;</span>\n<span class=\"token keyword\">const</span> uploadAssetToContentServer <span class=\"token operator\">=</span> <span class=\"token function\">require</span><span class=\"token punctuation\">(</span><span class=\"token string\">'./uploadAssetToContentServer'</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n<span class=\"token keyword\">const</span> createOrUpdateWidgetEntry <span class=\"token operator\">=</span> <span class=\"token function\">require</span><span class=\"token punctuation\">(</span><span class=\"token string\">'./createOrUpdateWidgetEntry'</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n\n<span class=\"token keyword\">const</span> <span class=\"token function-variable function\">deployWidget</span> <span class=\"token operator\">=</span> <span class=\"token keyword\">async</span> <span class=\"token punctuation\">(</span><span class=\"token parameter\"><span class=\"token punctuation\">{</span> widget <span class=\"token punctuation\">}</span></span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">{</span>\n    <span class=\"token keyword\">const</span> bundleFile <span class=\"token operator\">=</span> path<span class=\"token punctuation\">.</span><span class=\"token function\">join</span><span class=\"token punctuation\">(</span>\n        process<span class=\"token punctuation\">.</span><span class=\"token function\">cwd</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span>\n        <span class=\"token string\">'dist'</span><span class=\"token punctuation\">,</span>\n        <span class=\"token template-string\"><span class=\"token template-punctuation string\">`</span><span class=\"token string\">widget_</span><span class=\"token interpolation\"><span class=\"token interpolation-punctuation punctuation\">${</span>widget<span class=\"token interpolation-punctuation punctuation\">}</span></span><span class=\"token string\">_bundle.js</span><span class=\"token template-punctuation string\">`</span></span>\n    <span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n    <span class=\"token keyword\">const</span> uploadedUrl <span class=\"token operator\">=</span> <span class=\"token keyword\">await</span> <span class=\"token function\">uploadAssetToContentServer</span><span class=\"token punctuation\">(</span>bundleFile<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n    <span class=\"token keyword\">const</span> html <span class=\"token operator\">=</span> <span class=\"token template-string\"><span class=\"token template-punctuation string\">`</span><span class=\"token string\">\n        &lt;div id=\"widget:</span><span class=\"token interpolation\"><span class=\"token interpolation-punctuation punctuation\">${</span>widget<span class=\"token interpolation-punctuation punctuation\">}</span></span><span class=\"token string\">\">&lt;/div>\n        &lt;script defer src=\"</span><span class=\"token interpolation\"><span class=\"token interpolation-punctuation punctuation\">${</span>uploadedUrl<span class=\"token interpolation-punctuation punctuation\">}</span></span><span class=\"token string\">\">&lt;/script>\n    </span><span class=\"token template-punctuation string\">`</span></span><span class=\"token punctuation\">;</span>\n    <span class=\"token keyword\">await</span> <span class=\"token function\">createOrUpdateWidgetEntry</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">{</span>\n        name<span class=\"token operator\">:</span> widget<span class=\"token punctuation\">,</span>\n        html<span class=\"token punctuation\">,</span>\n    <span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n    console<span class=\"token punctuation\">.</span><span class=\"token function\">log</span><span class=\"token punctuation\">(</span><span class=\"token template-string\"><span class=\"token template-punctuation string\">`</span><span class=\"token string\">widget </span><span class=\"token interpolation\"><span class=\"token interpolation-punctuation punctuation\">${</span>widget<span class=\"token interpolation-punctuation punctuation\">}</span></span><span class=\"token string\"> deployed successfully</span><span class=\"token template-punctuation string\">`</span></span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">}</span><span class=\"token punctuation\">;</span>\n\n<span class=\"token function\">deployWidget</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">{</span>\n    widget<span class=\"token operator\">:</span> argv<span class=\"token punctuation\">.</span>widget<span class=\"token punctuation\">,</span>\n<span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">catch</span><span class=\"token punctuation\">(</span>console<span class=\"token punctuation\">.</span>error<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></code></pre></div>\n<p><strong>NOTE:</strong> I encapsulated the logic to upload the bundle file and save widget entry in <code class=\"language-text\">uploadAssetToContentServer.js</code> and <code class=\"language-text\">createOrUpdateWidgetEntry.js</code> respectively, which you will need to implement.</p>\n<p>In <code class=\"language-text\">package.json</code></p>\n<div class=\"gatsby-highlight\" data-language=\"javascript\"><pre class=\"language-javascript\"><code class=\"language-javascript\"><span class=\"token operator\">...</span>\n<span class=\"token string\">\"scripts\"</span><span class=\"token operator\">:</span> <span class=\"token punctuation\">{</span>\n    <span class=\"token operator\">...</span><span class=\"token punctuation\">.</span>\n    <span class=\"token string\">\"deploy-widget\"</span><span class=\"token operator\">:</span> <span class=\"token string\">\"webpack &amp;&amp; ./scripts/deployWidget\"</span>\n<span class=\"token punctuation\">}</span></code></pre></div>\n<p>And now to deploy the login widget:</p>\n<div class=\"gatsby-highlight\" data-language=\"text\"><pre class=\"language-text\"><code class=\"language-text\">npm run deploy-widget -- --widget login</code></pre></div>\n<p>Going back to the backend repository, You can render a specific widget using the html value saved in DB, for example</p>\n<div class=\"gatsby-highlight\" data-language=\"text\"><pre class=\"language-text\"><code class=\"language-text\">...\n{{ getWidgetHtmlFromDB('login') | raw }}\n...</code></pre></div>\n<h3>Pros</h3>\n<ul>\n<li>You have full control over what to put in the widget html so it's quite easy to enable SSR, critical css, ...etc.</li>\n<li>The development and deployment processes for frontend is totally separated from backend (happier developers).</li>\n<li>Deployment process is much faster which will make daily AB tests more realistic.</li>\n<li>More suited for larger teams where separation between frontend and backend is more clear.</li>\n</ul>\n<h3>Cons</h3>\n<ul>\n<li>Remember the saying \"with great flexibility comes great responsibility\"? The widget deployment process is merely updating an entry in DB, if you didn't build proper versioning around this feature or you allowed developers to push directly to production DB then disasters might happen.</li>\n<li>SSR is quite hacky with dynamic data... doable but hacky.</li>\n<li>Needs a lot of work on the backend side to integrate and maintain this feature properly in the CMS.</li>\n</ul>\n<hr>\n<h2>What's next</h2>\n<ul>\n<li>Having one vendor file that's shared between all widgets. @see <a href=\"https://webpack.js.org/plugins/dll-plugin/\">webpack DllPlugin</a></li>\n<li>\n<p>For <code class=\"language-text\">Standalone Approach</code></p>\n<ul>\n<li>Add Server Side Rendering and critical css in <code class=\"language-text\">deployWidget.js</code> script.</li>\n<li>Add versioning for the widget entry in CMS i.e. each widget deployment should be associated with a version number that you can rollback in CMS.</li>\n<li>Only allow the script <code class=\"language-text\">deployWidget.js</code> to deploy widgets to QA env. and create the scary-red \"Move to production\" button in QA CMS to just copy the entry from QA DB to Production DB.</li>\n</ul>\n</li>\n</ul>","fields":{"slug":"/embeddable-leightweight-react-widgets/","tags":["auto1","engineering","react","widgets","refactoring","modularity"]}}}]}},"pageContext":{"slug":"/tags/react","tag":"react","categories":["Architecture","Coding","DevOps","Engineering","ProjectManagement","QA","Social","TechRadar"]}}