<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: Bedrock</title>
    <description>The latest articles on Forem by Bedrock (@bedrock).</description>
    <link>https://forem.com/bedrock</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Forganization%2Fprofile_image%2F2248%2Fd91fa585-ac4a-4ec8-bcde-cf103067fa19.jpg</url>
      <title>Forem: Bedrock</title>
      <link>https://forem.com/bedrock</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/bedrock"/>
    <language>en</language>
    <item>
      <title>Best practices for Web application maintenance</title>
      <dc:creator>Antoine Caron</dc:creator>
      <pubDate>Sun, 05 Sep 2021 00:00:00 +0000</pubDate>
      <link>https://forem.com/bedrock/best-practices-for-web-application-maintenance-2hgl</link>
      <guid>https://forem.com/bedrock/best-practices-for-web-application-maintenance-2hgl</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;How not to throw away your application every two years?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Feedback based on best practices applied to the web platform developed at &lt;em&gt;&lt;a href="https://www.bedrockstreaming.com/" rel="noopener noreferrer"&gt;Bedrock Streaming&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  A bit of context
&lt;/h2&gt;

&lt;p&gt;At Bedrock Streaming many teams develop and maintain &lt;em&gt;frontend&lt;/em&gt; applications for our customers and users. Some of those application are not very young. In fact, the application I’m mainly working on is a website whose developments started in 2014. I have already mentioned it in different articles of &lt;a href="https://slashgear.github.io/" rel="noopener noreferrer"&gt;this blog&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F29uchi6ycdljaxu6y4gf.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F29uchi6ycdljaxu6y4gf.png" alt="screenshot of the number of commits on master of our project 15668"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You might think: “Oh poor people, maintaining an almost 10 year old application must be hell!”&lt;/p&gt;

&lt;p&gt;Don’t worry, it’s not the case! I have worked on projects that are much less old but where the development of new features was much more painful.&lt;/p&gt;

&lt;p&gt;Today the project is technically up to date, we must be on the latest version of React while it had started on a version &lt;em&gt;0.x.x&lt;/em&gt;. In this world of web technologies often criticized (eg: the many articles on the &lt;em&gt;Javascript Fatigue&lt;/em&gt;) whose tools and practices are constantly evolving, keeping a project “up to date” remains a real challenge.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmsvckhjbg2tatv7daqfm.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmsvckhjbg2tatv7daqfm.png" alt="number of versions of the application 1445"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Moreover, in the context of this project, in almost 10 years, we have had about 100 contributors. Some have only stayed a few months/years. How can we keep the maximum knowledge on “How we do things and how it works?” in such a moving human context?&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fr3df7n6n27wsu2vw7mp8.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fr3df7n6n27wsu2vw7mp8.png" alt="list of the 100 contributors of the project"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This is what I would like to present you.&lt;/p&gt;

&lt;p&gt;With the help of my colleagues, I have collected the list of good practices that still allow us to maintain this project today. With &lt;a href="https://twitter.com/fooragnak" rel="noopener noreferrer"&gt;Florent Dubost&lt;/a&gt;, we often thought that it would be interesting to publish it. We hope you will find it useful.&lt;/p&gt;

&lt;h2&gt;
  
  
  Set rules and automate them
&lt;/h2&gt;

&lt;p&gt;A project that stands the test of time is first and foremost a set of knowledge that is stacked one on top of the other. It’s like the Kapla tower you used to build as a child, trying to get as high as possible. A solid base on which we hope to add as much as possible before a potential fall.&lt;/p&gt;

&lt;p&gt;From the beginning of a project, we have to make important decisions about “How do we want to do things? We think for example about “What format for our files? How do we name this or that thing?” Writing accurate documentation of “How we do things” might seem like a good idea.&lt;/p&gt;

&lt;p&gt;However, documentation is cool, but it tends to get outdated very quickly. Our decisions evolve, but documentation does not.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;“Times change but not READMEs.”&lt;/p&gt;

&lt;p&gt;&lt;a href="https://twitter.com/omansour" rel="noopener noreferrer"&gt;&lt;em&gt;Olivier Mansour (deputy CTO at Bedrock)&lt;/em&gt;&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Automating the checking of each of the rules we impose on ourselves (on our codebase or our processes) is much more durable. To make it simple, we avoid as much as possible to say “We should do things like that”, and we prefer “we’ll code something that checks it for us”. On top of that, on the JS side we are really well equipped with tools like &lt;a href="https://eslint.org/" rel="noopener noreferrer"&gt;Eslint&lt;/a&gt; that allow us to implement our own rules.&lt;/p&gt;

&lt;p&gt;So the reflex we try to adopt is the following:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;“We should try to do it like this now!”&lt;/li&gt;
&lt;li&gt;“Ok that’s interesting, but how can we make sure we do it like that automatically with our CI (Continuous Integration)?”&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Continuous Integration of a project is the perfect solution to not miss anything on every &lt;em&gt;Pull Request&lt;/em&gt; we provide. Reviews are only easier because you don’t have to worry about all the rules that are already automated. In this model, the review is more for knowledge sharing than for typo copying and other non-compliance with the project conventions.&lt;/p&gt;

&lt;p&gt;In this principle, we must therefore try to banish oral rules. The time of the druids is over, if all the good practices of a project have to be transmitted orally, it will only take longer to guide new developers into your team.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9pgsd2t3t620aivnba6e.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9pgsd2t3t620aivnba6e.gif" alt="the recipe of the magic potion of panoramix is lost because secret"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;A project is not set in stone. These rules evolve with time. It is therefore preferable to add rules that have a script that will &lt;em&gt;autofix&lt;/em&gt; the whole codebase intelligently. Many Eslint rules offer this, and it is a very important selection criteria when choosing new conventions.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;eslint --fix
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A very strict rule that will force you to modify your code manually before each push is annoying in the long run and will annoy your teams. Whereas a rule (even a very strict one) that can auto-fix itself at commit time will not be seen as annoying.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;How to decide to add new rules ?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;This question may seem thorny, take for example the case of &lt;code&gt;&amp;lt;tab&amp;gt;&lt;/code&gt; / &lt;code&gt;&amp;lt;space&amp;gt;&lt;/code&gt; in files. For this, we try to avoid the endless debates and follow the trend and rules of the community. For example, &lt;a href="https://github.com/M6Web/eslint-tools" rel="noopener noreferrer"&gt;our Eslint configuration base&lt;/a&gt; is based on Airbnb’s which seems to have some success in the JS community. But if the rule we want to impose on ourselves is not available in Eslint or other tools, we sometimes prefer not to follow the rule rather than say “We’ll do it without a checking CI”.&lt;/p&gt;

&lt;h3&gt;
  
  
  The &lt;em&gt;almost&lt;/em&gt; exhaustive list 🤞
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4gz64al4km1bmm6xf3s4.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4gz64al4km1bmm6xf3s4.png" alt="Our continuous integration workflow"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The file format is tracked managed by &lt;a href="https://editorconfig.org/" rel="noopener noreferrer"&gt;Editorconfig&lt;/a&gt;, &lt;a href="https://prettier.io/" rel="noopener noreferrer"&gt;prettier&lt;/a&gt; and &lt;a href="https://eslint.org/" rel="noopener noreferrer"&gt;Eslint&lt;/a&gt;. We have opensourced &lt;a href="https://github.com/M6Web/eslint-tools" rel="noopener noreferrer"&gt;our own configuration&lt;/a&gt;, if it is of any use to you.&lt;/li&gt;
&lt;li&gt;We use a &lt;a href="https://www.conventionalcommits.org/en/v1.0.0/" rel="noopener noreferrer"&gt;specific commit name&lt;/a&gt; to generate our changelog. To make sure devs follow it, a simple step in our CI checks it.&lt;/li&gt;
&lt;li&gt;We don’t want a dev to make our JS bundles very big in production, so we track and measure their size in the CI. We use an in-house tool but we can recommend the [BuildTracker] tool (&lt;a href="https://buildtracker.dev/" rel="noopener noreferrer"&gt;https://buildtracker.dev/&lt;/a&gt;).&lt;/li&gt;
&lt;li&gt;Test coverage is not an indicator for the team, not all lines have the same need for us to be tested. Some teams at Bedrock however follow this indicator which at least has the interest to give a trend.&lt;/li&gt;
&lt;li&gt;Our unit tests obviously run on the CI, these must pass.&lt;/li&gt;
&lt;li&gt;Our functional tests (End to end: E2E) run on Chrome Headless, they must be green.&lt;/li&gt;
&lt;li&gt;The logs of our E2E tests are retrieved and parsed to avoid errors or React warnings (the parsing script is however complicated to maintain)&lt;/li&gt;
&lt;li&gt;Functional tests run in a &lt;em&gt;sandbox&lt;/em&gt; where the whole network is proxied. We make sure that our tests do not depend on a non mocked API that could slow down their execution.&lt;/li&gt;
&lt;li&gt;During the E2E tests we check that no image request has generated a 404.&lt;/li&gt;
&lt;li&gt;We perform some &lt;a href="https://www.deque.com/axe/" rel="noopener noreferrer"&gt;accessibility checks with Axe&lt;/a&gt; during our E2E tests.&lt;/li&gt;
&lt;li&gt;We check some rules on the CSS with &lt;a href="https://stylelint.io/" rel="noopener noreferrer"&gt;Stylelint&lt;/a&gt; and &lt;a href="https://github.com/M6Web/bemlinter" rel="noopener noreferrer"&gt;bemlinter&lt;/a&gt; (we don’t use BEM anymore but there is still some style managed in SCSS that we migrate little by little in StyledComponent)&lt;/li&gt;
&lt;li&gt;The project is a monorepo on which we try to maintain the same dependencies versions for each package. For that we have developed a tool that allows to do this check &lt;em&gt;&lt;a href="https://www.npmjs.com/package/monorepo-dependencies-check" rel="noopener noreferrer"&gt;monorepo-dependencies-check&lt;/a&gt;&lt;/em&gt;
&lt;/li&gt;
&lt;li&gt;We check that our &lt;code&gt;yarn.lock&lt;/code&gt; file has not been inadvertently modified or that it has been updated with respect to the modifications of the &lt;code&gt;package.json&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://www.terraform.io/" rel="noopener noreferrer"&gt;Terraform&lt;/a&gt; is used to manage our cloud resources, we check that the file format is correct.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Test, test, test
&lt;/h2&gt;

&lt;p&gt;I hope that in 2021 it is no longer necessary to explain why automatic testing of your application is essential to make it sustainable. In JS, we are rather well equipped in terms of testing tools today. However, the eternal question remains:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;“What do we want to test?”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Globally if we search on the internet this question, we see that different needs make emerge very different practices and testing tools. It would be very presumptuous to think that there is a good way to automatically test your application. This is why it is preferable to define one or more test strategies that meet defined and limited needs.&lt;/p&gt;

&lt;p&gt;Our test strategies are based on two distinct goals:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;To automate the verification of the functionalities proposed to the users by putting ourselves in their place.&lt;/li&gt;
&lt;li&gt;To provide us with efficient solutions to specify the way we implement our technical solutions to allow us to make them evolve more easily.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;To do this, we perform two “types of tests” that I propose to present here.&lt;/p&gt;

&lt;h3&gt;
  
  
  Our E2E tests
&lt;/h3&gt;

&lt;p&gt;We call them “functional tests”, they are End-to-end (E2E) tests on a very efficient technical stack composed of &lt;a href="https://cucumber.io/docs/installation/javascript/" rel="noopener noreferrer"&gt;CucumberJS&lt;/a&gt;, &lt;a href="https://webdriver.io/" rel="noopener noreferrer"&gt;WebdriverIO&lt;/a&gt; with &lt;a href="https://developers.google.com/web/updates/2017/04/headless-chrome" rel="noopener noreferrer"&gt;ChromeHeadless&lt;/a&gt;This is a technical stack set up at the beginning of the project (at the time with &lt;a href="https://phantomjs.org/" rel="noopener noreferrer"&gt;PhantomJS&lt;/a&gt; for the oldest among you)&lt;/p&gt;

&lt;p&gt;This stack allows us to automate the piloting of tests that control a browser. This browser will perform actions that are as close as possible to what our real users can do while checking how the site reacts.&lt;/p&gt;

&lt;p&gt;A few years ago, this technical stack was rather complicated to set up, but today it is rather simple to do.&lt;a href="https://github.com/Slashgear/slashgear.github.io" rel="noopener noreferrer"&gt;The site that hosts this blog post&lt;/a&gt; is itself proof of this. It only took me about ten minutes to set up this stack with &lt;a href="https://webdriver.io/docs/gettingstarted" rel="noopener noreferrer"&gt;the WebdriverIo CLI&lt;/a&gt; to verify that my blog is working as expected.&lt;/p&gt;

&lt;p&gt;I recently published &lt;a href="https://dev.to/slashgear_/how-to-setup-end-to-end-tests-with-webdriverio-on-github-action-f9n"&gt;an article presenting the implementation of this stack&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;So here is an example of an E2E test file to give you an idea:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight gherkin"&gt;&lt;code&gt;&lt;span class="kd"&gt;Feature&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; Playground

  &lt;span class="kn"&gt;Background&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; Playground context
    &lt;span class="nf"&gt;Given &lt;/span&gt;I use &lt;span class="s"&gt;"playground"&lt;/span&gt; test context

  &lt;span class="kn"&gt;Scenario&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; Check if playground is reachable
    &lt;span class="nf"&gt;When &lt;/span&gt;As user &lt;span class="s"&gt;"toto@toto.fr"&lt;/span&gt; I visit the &lt;span class="s"&gt;"playground"&lt;/span&gt; page
    &lt;span class="nf"&gt;And &lt;/span&gt;I click on &lt;span class="s"&gt;"playground trigger"&lt;/span&gt;
    &lt;span class="nf"&gt;Then &lt;/span&gt;I should see a &lt;span class="s"&gt;"visible playground"&lt;/span&gt;
    &lt;span class="nf"&gt;And &lt;/span&gt;I should see 4 &lt;span class="s"&gt;"playground tab"&lt;/span&gt; in &lt;span class="s"&gt;"playground"&lt;/span&gt;

    &lt;span class="nf"&gt;When &lt;/span&gt;I click on &lt;span class="s"&gt;"playground trigger"&lt;/span&gt;
    &lt;span class="nf"&gt;Then &lt;/span&gt;I should not see a &lt;span class="s"&gt;"visible playground"&lt;/span&gt;

    &lt;span class="c"&gt;# ...&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And it looks like this in local with my Chrome browser!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fx52jbcyoxk2eqdjcmyav.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fx52jbcyoxk2eqdjcmyav.gif" alt="Example of functional test execution"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Here is a diagram that explains how this stack works:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4gwupuk6jz3ipa3u0e8z.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4gwupuk6jz3ipa3u0e8z.png" alt="diagram that explains how our stack works"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Today, Bedrock’s web application has over 800 E2E test cases running on each of our &lt;em&gt;Pull Request&lt;/em&gt; and the &lt;code&gt;master&lt;/code&gt; branch. They assure us that we are not introducing any functional regression and that’s just great!&lt;/p&gt;

&lt;p&gt;👍 The positives&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;WebdriverIO also allows us to run these same tests on real devices on a daily basis through the paid SAAS service &lt;a href="https://www.browserstack.com/" rel="noopener noreferrer"&gt;Browserstack&lt;/a&gt;. So we have every day a &lt;em&gt;job&lt;/em&gt; that makes sure that our site works correctly on a Chrome last version on Windows 10 and Safari on MacOs.&lt;/li&gt;
&lt;li&gt;These tests allow us to easily document the functionality of the application using the Gherkin language.&lt;/li&gt;
&lt;li&gt;They allow us to reproduce cases that are far from nominal. In a &lt;em&gt;TDD&lt;/em&gt; logic, they allow us to advance on the development without having to click for hours.&lt;/li&gt;
&lt;li&gt;These tests allowed us not to break the old version of the site which is still in production for some customers while our efforts are concentrated on the new one.&lt;/li&gt;
&lt;li&gt;They give us real confidence.&lt;/li&gt;
&lt;li&gt;Thanks to our library &lt;a href="https://www.npmjs.com/package/superagent-mock" rel="noopener noreferrer"&gt;&lt;em&gt;superagent-mock&lt;/em&gt;&lt;/a&gt;, we can &lt;em&gt;fixturer&lt;/em&gt; (plug, mock) all the APIs we depend on and thus even check the error cases. Also, mocking the browser’s XHR layer allows for a significant improvement in test execution time. 🚀&lt;/li&gt;
&lt;li&gt;They give us access to extended uses like:

&lt;ul&gt;
&lt;li&gt;checking accessibility rules&lt;/li&gt;
&lt;li&gt;check the browser console logs (to avoid introducing errors or React Warning for example)&lt;/li&gt;
&lt;li&gt;monitoring all network calls of the site through a proxy&lt;/li&gt;
&lt;li&gt;and so on…&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;👎 The complications&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Maintaining this stack is complicated and expensive. Since few resources are published on this domain, we sometimes find ourselves digging for days to fix them 😅. Sometimes we feel quite alone in having these worries.&lt;/li&gt;
&lt;li&gt;It is very easy to code a so-called &lt;em&gt;flaky&lt;/em&gt; E2E test (ie: a test that can fail randomly). They make us think that something is broken. They sometimes take us a long time to stabilize. It is still &lt;strong&gt;much better to remove a test that will not give you a stable result.&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Running all the tests takes a lot of time on our continuous integration. We must regularly work on their optimization so that the feedback they provide you is as fast as possible. These important times also cost money, because we have to run these tests on machines. For your information, the infrastructure of the website (just the hosting of our Node servers + static files + CDN) cost much less than our continuous integration. This obviously makes our Ops team smile! 😊&lt;/li&gt;
&lt;li&gt;The new recruits in our teams have often never done this kind of testing, so there is a &lt;del&gt;struggle&lt;/del&gt; phase of learning…&lt;/li&gt;
&lt;li&gt;Some features are sometimes too complicated to test with our E2E stack (for example, payment paths that depend on third parties). So we sometimes fall back on other techniques with Jest, especially with a less unitary scope.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Our “unit” tests
&lt;/h3&gt;

&lt;p&gt;To complete our functional tests we also have a stack of tests written with &lt;a href="https://jestjs.io/en/" rel="noopener noreferrer"&gt;Jest&lt;/a&gt;. We call these tests unit tests because we have as a principle to try to always test our JS modules independently from the others.&lt;/p&gt;

&lt;p&gt;Let’s not debate here about “Are these real unit tests?”, there are enough articles on the internet about this topic.&lt;/p&gt;

&lt;p&gt;We use these tests for different reasons that cover needs that our functional tests do not cover:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;to help us develop our JS modules with TDD practices.&lt;/li&gt;
&lt;li&gt;to document and describe how a JS module works.&lt;/li&gt;
&lt;li&gt;test very/too complicated edge cases with our E2E tests.&lt;/li&gt;
&lt;li&gt;facilitate the refactoring of our application by showing us the technical impacts of our modifications.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;With these tests, we put ourselves at the level of a utility function, a Redux action, a reducer, a React component. We rely mainly on &lt;a href="https://dev.to/slashgear_/discover-jest-hidden-feature-automock-43i0-temp-slug-9168332"&gt;the &lt;code&gt;automock&lt;/code&gt; functionality of Jest&lt;/a&gt; which allows us to isolate our JS modules when we test.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fuq1lhc2748xg9ts1nwzw.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fuq1lhc2748xg9ts1nwzw.jpg" alt="visual representation of the automock"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The previous image represents the metaphor that allows us to explain our unit testing strategy to newcomers.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;You have to imagine that the application is a wall made of unit bricks (our ecmascript modules), our unit tests must test one by one the bricks in total independence from the others. Our functional tests are there to test the cement between the bricks.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;To summarize, we could say that our E2E tests test &lt;em&gt;what our application should do&lt;/em&gt;, and our unit tests make sure to check &lt;em&gt;how it works.&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Today there are more than 6000 unit tests that cover the application and allow to limit regressions.&lt;/p&gt;

&lt;p&gt;👍&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://jestjs.io/en/" rel="noopener noreferrer"&gt;Jest&lt;/a&gt; is really a great library, fast, complete, well documented.&lt;/li&gt;
&lt;li&gt;Unit tests help us a lot to understand &lt;em&gt;several years later&lt;/em&gt; how it all works.&lt;/li&gt;
&lt;li&gt;We always manage to unit test our code, and it complements our E2E tests well.&lt;/li&gt;
&lt;li&gt;The &lt;code&gt;automock&lt;/code&gt; is really handy for breaking down tests by modules.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;👎&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Sometimes we found ourselves limited by our E2E test stack and couldn’t rely solely on unit tests. We were missing something to be able to make sure that the &lt;em&gt;cement between the bricks&lt;/em&gt; worked as we wanted it to. For this, a second test stack &lt;a href="https://jestjs.io/en/" rel="noopener noreferrer"&gt;Jest&lt;/a&gt; was set up called “integration test” where the &lt;code&gt;automock&lt;/code&gt; is disabled.&lt;/li&gt;
&lt;li&gt;The abuse of &lt;a href="https://jestjs.io/docs/snapshot-testing" rel="noopener noreferrer"&gt;&lt;em&gt;Snapshot&lt;/em&gt;&lt;/a&gt; is dangerous for your health. The use of &lt;em&gt;“Snapshot testing”&lt;/em&gt; can save time on the implementation of your tests but can reduce the quality. Having to review a 50 line object in &lt;em&gt;Snapshot&lt;/em&gt; is neither easy nor relevant.&lt;/li&gt;
&lt;li&gt;With the depreciation of &lt;a href="https://enzymejs.github.io/enzyme/" rel="noopener noreferrer"&gt;EnzymeJS&lt;/a&gt;, we are forced to migrate to &lt;a href="https://testing-library.com/docs/react-testing-library/intro/" rel="noopener noreferrer"&gt;React Testing Library&lt;/a&gt;. It is of course possible to unit test components with this new library. Unfortunately, this is not really the spirit and the way to do it.&lt;a href="https://testing-library.com/docs/react-testing-library/intro/" rel="noopener noreferrer"&gt;React Testing Library&lt;/a&gt; pushes us &lt;a href="https://kentcdodds.com/blog/why-i-never-use-shallow-rendering" rel="noopener noreferrer"&gt;not to play with &lt;em&gt;shallow rendering&lt;/em&gt;&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Our principles
&lt;/h3&gt;

&lt;p&gt;We try to always follow the following rules when asking the question “Should I add tests?“.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;If our &lt;em&gt;Pull Request&lt;/em&gt; introduces new user features, we need to integrate E2E test scenarios. Unit tests with Jest can complete / replace them accordingly.&lt;/li&gt;
&lt;li&gt;If our &lt;em&gt;Pull Request&lt;/em&gt; aims to fix a bug, it means that we are missing a test case. We must therefore try to add an E2E test or, failing that, a unit test.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;em&gt;It is while writing these lines that I think that these principles could very well be automated.&lt;/em&gt; 🤣&lt;/p&gt;

&lt;h2&gt;
  
  
  The project stays, the features don’t
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;“The second evolution of a feature is very often its removal.”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;As a matter of principle, we want to make sure that every new feature in the application does not base its activation on simply being in the codebase. Typically, the lifecycle of a feature in a project can be as follows (in a &lt;a href="https://guides.github.com/introduction/flow/" rel="noopener noreferrer"&gt;Github Flow&lt;/a&gt;):&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;a person implements on a branch&lt;/li&gt;
&lt;li&gt;the feature is &lt;em&gt;merged&lt;/em&gt; on master&lt;/li&gt;
&lt;li&gt;it is deployed in production&lt;/li&gt;
&lt;li&gt;lives its feature life (sometimes with bugs and fixes)&lt;/li&gt;
&lt;li&gt;the feature is not needed anymore&lt;/li&gt;
&lt;li&gt;a person unravels the code and removes it&lt;/li&gt;
&lt;li&gt;new deployment&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;To simplify some steps, we have implemented &lt;em&gt;feature flipping&lt;/em&gt; on the project.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;How does it work?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;In our config there is a &lt;em&gt;map&lt;/em&gt; key/value that lists all the features of the application associated with their activation status.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;featureFlipping&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;myAwesomeFeature&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;anotherOne&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In our code, we have implemented conditional treatments that say “If this feature is activated then…“. This can change the rendering of a component, change the implementation of a Redux action or disable a route in our &lt;em&gt;react-router&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;But what’s the point?&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;We can develop new evolutions progressively by hiding them behind a configuration key. We deliver features in production without activating them.&lt;/li&gt;
&lt;li&gt;In a test environment, we can overload this config to test features that are not yet activated in production.&lt;/li&gt;
&lt;li&gt;In the case of a white label site, we can propose these features to our customers as possible options.&lt;/li&gt;
&lt;li&gt;Before deleting code of a feature, we deactivate it and clean it up without risk.&lt;/li&gt;
&lt;li&gt;Thanks to an in-house tool called &lt;em&gt;Applaunch&lt;/em&gt;, this feature flipping config can be overloaded on time in a GUI without deployment. This allows us to activate features without putting the code into production. In the event of an incident, we can deactivate features that have been degraded.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;To give you a more concrete example, between 2018 and 2020 we completely overhauled the application’s interface. This graphical evolution was just a featureFlipping key. The graphical redesign was not a reset of the project, we still live with both versions (as long as the switchover of all our customers is not completed).&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8rqhmue6n3rahpvv0xtc.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8rqhmue6n3rahpvv0xtc.jpg" alt="screenshot comparing v4 / v5 on 6play"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  A/B testing
&lt;/h3&gt;

&lt;p&gt;Thanks to the great work of the backend and data teams, we were even able to extend the use of &lt;em&gt;feature flipping&lt;/em&gt; by making this configuration modifiable for sub-groups of users.&lt;/p&gt;

&lt;p&gt;This allows us to deploy new features on a smaller portion of users in order to compare our &lt;a href="https://en.wikipedia.org/wiki/Performance_indicator" rel="noopener noreferrer"&gt;KPI&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Decision making, technical or product performance improvement, experimentation, the possibilities are numerous and we exploit them more and more.&lt;/p&gt;

&lt;h3&gt;
  
  
  The &lt;em&gt;future flipping&lt;/em&gt;.
&lt;/h3&gt;

&lt;blockquote&gt;
&lt;p&gt;Based on an original idea by &lt;a href="https://twitter.com/SuperFlaw" rel="noopener noreferrer"&gt;Florent Lepretre&lt;/a&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;We regularly had the need to activate features at &lt;del&gt;very&lt;/del&gt; early hours in the future. For that we had to be connected at a precise time on our computer to modify the configuration on the fly.&lt;/p&gt;

&lt;p&gt;To avoid forgetting to do this, or doing it late, we made sure that a configuration key could be activated from a certain date. To do this, we evolved our &lt;em&gt;selector redux&lt;/em&gt; which indicated if a feature was activated so that it could handle date formats and compare them to the current time.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;featureFlipping&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;myAwesomeFeature&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;offDate&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;2021-07-12 20:30:00&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;onDate&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;2021-07-12 19:30:00&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;Many coffees ☕️ at 9am have been saved by &lt;em&gt;future flipping&lt;/em&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Monitor, Measure, Alert
&lt;/h2&gt;

&lt;p&gt;To maintain a project as long as bedrock’s web application, testing, documentation and rigor are not enough. You also need visibility on what works in production.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;“How do you know that the application you have in production right now is working as expected?”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;We assume that no functionality works until it is monitored. Today, monitoring in Bedrock on the frontend side takes the form of different tools and different stacks. I could quote &lt;a href="https://newrelic.com/" rel="noopener noreferrer"&gt;NewRelic&lt;/a&gt;, a &lt;a href="https://github.com/statsd/statsd" rel="noopener noreferrer"&gt;Statsd&lt;/a&gt;, a &lt;a href="https://www.elastic.co/fr/what-is/elk-stack" rel="noopener noreferrer"&gt;ELK&lt;/a&gt; stack or even &lt;a href="https://youbora.nicepeopleatwork.com/" rel="noopener noreferrer"&gt;Youbora&lt;/a&gt; for the video.&lt;/p&gt;

&lt;p&gt;To give you an example, each time a user starts a browsing session we send an anonymous monitoring &lt;em&gt;Hit&lt;/em&gt; to increment a counter in Statsd. We then have to define a dashboard that displays the evolution of this number in a graph. If we observe a too important variation, it can allow us to detect an incident.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcqewjsr2njehktz4dcxu.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcqewjsr2njehktz4dcxu.png" alt="example of monitoring dashboard"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Monitoring also offers us solutions to understand and analyze a bug that occurred in the past. Understanding an incident, explaining it, finding its root cause are the possibilities that are open to you if you monitor your application. Monitoring can also allow you to better communicate with your customers about the impact of an incident and also to estimate the number of impacted users.&lt;/p&gt;

&lt;p&gt;With the multiplication of our customers, monitoring our platforms well is not enough. Too much data, too many dashboards to monitor, it becomes very easy to miss something. So we started to complement our metrics monitoring with automatic &lt;em&gt;alerting&lt;/em&gt;. Once we have enough confidence in the metrics, we can easily set up alerts that will warn us if there is an inconsistent value.&lt;/p&gt;

&lt;p&gt;However, we try to always trigger alerts only when it is actionable. In other words, if an alert sounds, we have something to do. Sounding alerts that do not require immediate human action generates noise and wastes time.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fsa03ytio1zueetbeeuxb.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fsa03ytio1zueetbeeuxb.gif" alt="general alert"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Limit, monitor and update your dependencies
&lt;/h2&gt;

&lt;p&gt;What goes out of date faster than your shadow in a web project based on javascript technologies are your dependencies. The ecosystem evolves rapidly and your dependencies can quickly become unmaintained, out of fashion or completely overhauled with big &lt;em&gt;breaking changes&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;We therefore try as much as possible to limit our dependencies and avoid adding them unnecessarily. A dependency is often very easy to add but it can become a real headache to remove.&lt;/p&gt;

&lt;p&gt;The graphic component libraries (e.g. React bootstrap, Material Design) are a good example of dependencies that we do not want to introduce. They can make integration easier at first, but they often freeze the version of your component library later on. You don’t want to freeze the React version in your application for two form components.&lt;/p&gt;

&lt;p&gt;Monitoring is also part of our dependency management routines. Since the addition of &lt;a href="https://docs.npmjs.com/auditing-package-dependencies-for-security-vulnerabilities" rel="noopener noreferrer"&gt;reporting security flaws in an NPM package&lt;/a&gt;, it is possible to know if a project has a dependency that contains a known security flaw with a simple command. So we have daily jobs on our projects that run the &lt;code&gt;yarn audit&lt;/code&gt; command to force us to apply patches.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Dependency maintenance is greatly facilitated by our E2E test stack which sounds the alarm if the version upgrade generates a regression.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Today, except for security flaws, we update our dependencies “when we have time”, often at the end of &lt;em&gt;sprint&lt;/em&gt;. We are not satisfied with this because some dependencies can be forgotten. I personally use tools like &lt;a href="https://classic.yarnpkg.com/en/docs/cli/outdated/" rel="noopener noreferrer"&gt;&lt;code&gt;yarn outdated&lt;/code&gt;&lt;/a&gt; and &lt;a href="https://dependabot.com/" rel="noopener noreferrer"&gt;Dependabot&lt;/a&gt; on my personal projects to automate the update of my dependencies.&lt;/p&gt;

&lt;h2&gt;
  
  
  Accepting your technical debt
&lt;/h2&gt;

&lt;p&gt;A project will always accumulate technical debt. &lt;strong&gt;This is a fact.&lt;/strong&gt; Whether it is voluntary or involuntary debt, a project that resists the years will inevitably accumulate debt. Even more so, if during all these years you keep adding features.&lt;/p&gt;

&lt;p&gt;Since 2014, our best practices, our ways of doing things have evolved well. Sometimes we decided these changes but sometimes we underwent them (an example, the arrival of functional components with React and the Hooks api).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Our project is not completely &lt;em&gt;“state of art”&lt;/em&gt; and we assume it.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fdj9koo9ksvhoopaidmst.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fdj9koo9ksvhoopaidmst.gif" alt="It will hold!"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We try to prioritize our &lt;em&gt;refactoring&lt;/em&gt; topics on the parts of the application on which we have the most concern, the most pain. We consider that a part of the application that we don’t like but on which we don’t need to work (bring evolutions) doesn’t deserve that we refactor it.&lt;/p&gt;

&lt;p&gt;I could name many features of our application that have not evolved functionally for several years. But since we have covered these features with E2E tests since the beginning, we didn’t really have to touch them.&lt;/p&gt;

&lt;p&gt;As said above, the next evolution of a code feature is sometimes its deactivation. So why spend time rewriting the whole application?&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;In any case, the code becomes “legacy”.&lt;/li&gt;
&lt;li&gt;As long as the features are tested, nothing obliges us to refactor everything permanently so that our entire codebase is &lt;em&gt;state of art&lt;/em&gt;.&lt;/li&gt;
&lt;li&gt;We focus on our &lt;em&gt;pain points&lt;/em&gt;, we re-factor what we really need to evolve.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  To summarize
&lt;/h2&gt;

&lt;p&gt;The best practices presented here are obviously subjective and will not be perfectly/directly applicable in your contexts. However, I am convinced that they can probably help you identify what can make your project go from fun to stale. At Bedrock we have other practices in place that I haven’t listed here but that will be the occasion for a new article sometime.&lt;/p&gt;

&lt;p&gt;Finally, if you want me to go into more detail on some of the chapters presented here, don’t hesitate to tell me, I could try to dedicate a specific article to it.&lt;/p&gt;

</description>
      <category>web</category>
      <category>javascript</category>
    </item>
    <item>
      <title>React/Redux: pitfalls and best practices</title>
      <dc:creator>Antoine Caron</dc:creator>
      <pubDate>Mon, 27 Apr 2020 05:52:16 +0000</pubDate>
      <link>https://forem.com/bedrock/react-redux-pitfalls-and-best-practices-268k</link>
      <guid>https://forem.com/bedrock/react-redux-pitfalls-and-best-practices-268k</guid>
      <description>&lt;p&gt;After 2 years using React with Redux for the video platform &lt;a href="https://6play.fr" rel="noopener noreferrer"&gt;6play&lt;/a&gt;, I was able to identify good practices and pitfalls to avoid at all costs. The &lt;a href="https://www.bedrockstreaming.com/" rel="noopener noreferrer"&gt;Bedrock&lt;/a&gt; team (to which I currently belong) kept the technical stack of the project up to date to take advantage of the new features of &lt;code&gt;react&lt;/code&gt;, &lt;code&gt;react-redux&lt;/code&gt; and &lt;code&gt;redux&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;So here are my tips for maintaining and using React and Redux in your application without going mad.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;This article is not an introduction to React or Redux. I recommend &lt;a href="https://redux.js.org/basics/usage-with-react" rel="noopener noreferrer"&gt;this documentation&lt;/a&gt; if you want to see how to implement it in your applications.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;You could also take a look at &lt;a href="https://redux.js.org/style-guide/style-guide" rel="noopener noreferrer"&gt;Redux offical style guide&lt;/a&gt; in which you could find some of those tips and others. Note that if you use the &lt;a href="https://redux-toolkit.js.org/" rel="noopener noreferrer"&gt;Redux Toolkit&lt;/a&gt;, some of the tips/practices presented in this article are already integrated directly into the API.&lt;/p&gt;

&lt;h2&gt;
  
  
  Avoid having only one reducer
&lt;/h2&gt;

&lt;p&gt;The &lt;a href="https://redux.js.org/basics/reducers" rel="noopener noreferrer"&gt;reducer&lt;/a&gt; is the function that is in charge of building a new state at each &lt;code&gt;action&lt;/code&gt;.One might be tempted to manipulate only one reducer. In the case of a small application, this is not a problem. For applications expressing a complex and evolving business, it is better to opt in for the &lt;a href="https://redux.js.org/api/combinereducers" rel="noopener noreferrer"&gt;combineReducers&lt;/a&gt; solution.&lt;/p&gt;

&lt;p&gt;This feature of &lt;code&gt;redux&lt;/code&gt; allows to manipulate not one but several &lt;a href="https://redux.js.org/basics/reducers" rel="noopener noreferrer"&gt;reducer&lt;/a&gt;s which act respectively on the state.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;When and how to split its application?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;What we recommend at Bedrock is a functional splitting of the application.In my approach, we would tend to represent the business of the application more than the technical stuff implied.Some very good articles explain it notably through the use of &lt;a href="https://en.wikipedia.org/wiki/Domain-driven_design" rel="noopener noreferrer"&gt;DDD principles&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;In Bedrock, we use a folder named &lt;em&gt;modules&lt;/em&gt; which groups together the different folders associated with the feature of your application.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;app/
  modules/
    user/
      __tests__ /
        user.reducer.spec.js
      components/
      user.reducer.js
    product/
      __tests__ /
        product.reducer.spec.js
      components/
      product.reducer.js
    account/
      __tests__ /
      account.reducer.spec.js
      components/
      account.reducer.js
  store.js
  index.js
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So in &lt;code&gt;store.js&lt;/code&gt; all you need to do is combine your different reducers.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;createStore&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;combineReducers&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;redux&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;user&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./modules/user/user.reducer.js&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;product&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./modules/user/product.reducer.js&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;account&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./modules/user/account.reducer.js&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;store&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;createStore&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;combineReducers&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;product&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;account&lt;/span&gt; &lt;span class="p"&gt;}))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;By following this principle, you will:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;keep reducers readable because they have a limited scope&lt;/li&gt;
&lt;li&gt;structure and define the functionalities of your application&lt;/li&gt;
&lt;li&gt;facilitate the testing&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Historically, this segmentation has allowed us to remove complete application areas without having impacts on the entire codebase, just by deleting the &lt;code&gt;module&lt;/code&gt; folder associated with the feature.&lt;/p&gt;

&lt;h3&gt;
  
  
  Proxy access to the state
&lt;/h3&gt;

&lt;p&gt;Now that your reducers have been placed in the functional &lt;code&gt;module&lt;/code&gt;, you need to allow your components to access the state via &lt;code&gt;selector&lt;/code&gt;.A &lt;code&gt;selector&lt;/code&gt; is a function that has the &lt;code&gt;state&lt;/code&gt; as a parameter, and retrieves its information.This can also allow you to select only the props needed for the component by decoupling from the state structure.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;getUserName&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;user&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;lastName&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;lastName&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can also pass parameters to a &lt;code&gt;selector&lt;/code&gt; by wrapping it with a function.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;getProduct&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;productId&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;product&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;list&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;
  &lt;span class="nx"&gt;list&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;find&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;product&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;product&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="nx"&gt;productId&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This will allow you to use them in your components using the &lt;a href="https://redux.js.org/recipes/usage-with-typescript#typing-the-useselector-hook" rel="noopener noreferrer"&gt;useSelector&lt;/a&gt; hook.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;MyComponent&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;product&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useSelector&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;getProduct&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;12&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;div&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;product&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/div&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It is specified in the &lt;code&gt;react-redux&lt;/code&gt; doc that the &lt;em&gt;selector&lt;/em&gt; is called for each render of the component.If the &lt;code&gt;selector&lt;/code&gt; function reference does not change, a cached version of the object can be returned directly.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;app/
  modules/
    user/
      __tests__ /
        user.reducer.spec.js
      components/
      user.reducer.js
      user.selectors.js &amp;lt;--- This is where all module selectors are exported
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Prefix the name of your actions
&lt;/h3&gt;

&lt;blockquote&gt;
&lt;p&gt;I really advise you to define naming rules for your actions and if possible check them with an &lt;code&gt;eslint&lt;/code&gt; rule.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Actions are in uppercase letters separated by ’_’.Here an example with this action: &lt;code&gt;SET_USERS&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;app/
  modules/
    user/
      __tests__ /
        user.reducer.spec.js
      components/
      user.actions.js &amp;lt;--- This is where all module action creators are exported
      user.reducer.js
      user.selectors.js
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Action names are prefixed by the name of the &lt;code&gt;module&lt;/code&gt; in which it is located.This gives a full name: &lt;code&gt;user/SET_USERS&lt;/code&gt;.A big advantage of this naming rule is that you can easily filter the action in &lt;a href="https://github.com/reduxjs/redux-devtools" rel="noopener noreferrer"&gt;redux-devtools&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fruup1p56m5c0h6tv83cg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fruup1p56m5c0h6tv83cg.png" alt="Redux devtools"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Always test your reducers
&lt;/h3&gt;

&lt;p&gt;The &lt;code&gt;reducers&lt;/code&gt; are the holders of your application’s business.They manipulate the state of your application.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;This code is therefore &lt;em&gt;sensitive&lt;/em&gt;.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;➡️ A modification can have a lot of impact on your application.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;This code is rich in business rules&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;➡️ You must be confident that these are correctly implemented.&lt;/p&gt;

&lt;p&gt;The good news is that this code is relatively easy to test.A &lt;a href="https://redux.js.org/basics/reducers" rel="noopener noreferrer"&gt;reducer&lt;/a&gt; is a single function that takes 2 parameters.This function will return a new &lt;code&gt;state&lt;/code&gt; depending on the type of action and its parameters.&lt;/p&gt;

&lt;p&gt;This is the standard structure for testing &lt;a href="https://redux.js.org/basics/reducers" rel="noopener noreferrer"&gt;reducer&lt;/a&gt;s with &lt;a href="https://jestjs.io/" rel="noopener noreferrer"&gt;Jest&lt;/a&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nf"&gt;describe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;ReducerName&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;beforeEach&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Init a new state&lt;/span&gt;
  &lt;span class="p"&gt;})&lt;/span&gt;
  &lt;span class="nf"&gt;describe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;ACTION&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Group tests by action type&lt;/span&gt;
    &lt;span class="nf"&gt;it&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;should test action with some params&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{})&lt;/span&gt;
    &lt;span class="nf"&gt;it&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;should test action with other params&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{})&lt;/span&gt;
  &lt;span class="p"&gt;})&lt;/span&gt;
  &lt;span class="nf"&gt;describe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;SECOND_ACTION&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;it&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;should test action with some params&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{})&lt;/span&gt;
  &lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I also recommend that you use the &lt;a href="https://www.npmjs.com/package/deep-freeze" rel="noopener noreferrer"&gt;deep-freeze&lt;/a&gt; package on your &lt;code&gt;state&lt;/code&gt; to ensure that all actions return new references.&lt;/p&gt;

&lt;p&gt;Ultimately, testing your &lt;a href="https://redux.js.org/basics/reducers" rel="noopener noreferrer"&gt;reducer&lt;/a&gt;s will allow you to easily refactor the internal structure of their state without the risk of introducing regressions.&lt;/p&gt;

&lt;h2&gt;
  
  
  Keep the immutability and readability of your reducers
&lt;/h2&gt;

&lt;p&gt;A &lt;a href="https://redux.js.org/basics/reducers" rel="noopener noreferrer"&gt;reducer&lt;/a&gt; is a function that must return a new version of the state containing its new values while keeping the same references of the objects that have not changed.This allows you to take full advantage of &lt;em&gt;Structural sharing&lt;/em&gt; and avoid exploding your memory usage.The use of the &lt;em&gt;spread operator&lt;/em&gt; is thus more than recommended.&lt;/p&gt;

&lt;p&gt;However, in the case where the state has a complicated and deep structure, it can be verbose to change the state without destroying the references that should not change.&lt;/p&gt;

&lt;p&gt;For example, here we want to override the &lt;code&gt;Rhone.Villeurbanne.postal&lt;/code&gt; value of the state while keeping the objects that don’t change.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;state&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;Rhone&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;Lyon&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;postal&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;69000&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="na"&gt;Villeurbanne&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;postal&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;''&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="na"&gt;Isère&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;Grenoble&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;postal&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;39000&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// When you want to change nested state value and use immutability&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;newState&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;Rhone&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Lyon&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;Villeurbanne&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;postal&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;69100&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To avoid this, &lt;a href="https://github.com/flepretre" rel="noopener noreferrer"&gt;a member of the Bedrock team&lt;/a&gt; released a package that allows to &lt;code&gt;set&lt;/code&gt; nested attribute while ensuring immutability: &lt;a href="https://www.npmjs.com/package/immutable-set" rel="noopener noreferrer"&gt;immutable-set&lt;/a&gt;This package is much easier to use than tools like &lt;a href="https://immutable-js.github.io/immutable-js/" rel="noopener noreferrer"&gt;immutable.js&lt;/a&gt; because it does not use Object prototype.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="kd"&gt;set&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;immutable-set&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;newState&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;`Rhone.Villeurbanne.postal`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;69100&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Do not use the default case
&lt;/h2&gt;

&lt;p&gt;The implementation of a &lt;code&gt;redux&lt;/code&gt; &lt;a href="https://redux.js.org/basics/reducers" rel="noopener noreferrer"&gt;reducer&lt;/a&gt; very often consists of a &lt;code&gt;switch&lt;/code&gt; where each &lt;code&gt;case&lt;/code&gt; corresponds to an &lt;code&gt;action&lt;/code&gt;.A &lt;code&gt;switch&lt;/code&gt; must always define the &lt;code&gt;default&lt;/code&gt; case if you follow so basic &lt;code&gt;eslint&lt;/code&gt; rules.&lt;/p&gt;

&lt;p&gt;Let’s imagine the following &lt;a href="https://redux.js.org/basics/reducers" rel="noopener noreferrer"&gt;reducer&lt;/a&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;initialState&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;bar&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;index&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;reducer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;initialState&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;action&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;switch &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;action&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;type&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;FOO&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;foo&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="nl"&gt;default&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;bar&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We can naively say that this &lt;a href="https://redux.js.org/basics/reducers" rel="noopener noreferrer"&gt;reducer&lt;/a&gt; manages two different actions. It’s okay.If we isolate this &lt;a href="https://redux.js.org/basics/reducers" rel="noopener noreferrer"&gt;reducer&lt;/a&gt; there are only two types of &lt;code&gt;action' that can change this state; the&lt;/code&gt;FOO’ action and any other action.&lt;/p&gt;

&lt;p&gt;However, if you have followed the advice to cut out your reducers, you don’t have only one reducer acting on your blind.&lt;/p&gt;

&lt;p&gt;That’s where the previous &lt;a href="https://redux.js.org/basics/reducers" rel="noopener noreferrer"&gt;reducer&lt;/a&gt; is a problem.Indeed, any other action will change this state to a &lt;code&gt;default&lt;/code&gt; state.A &lt;code&gt;dispatch&lt;/code&gt; action will pass through each of the reducers associated with this one. An action at the other end of your application could affect this state without being expressed in the code.This should be avoided.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fmugtggg6hr6lkuv5cdsy.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fmugtggg6hr6lkuv5cdsy.png" alt="combineReducers"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you want to modify the state with an action from another module, you can do so by adding a &lt;code&gt;case&lt;/code&gt; on that action.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;reducer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;initialState&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;action&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;switch &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;action&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;type&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;FOO&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;foo&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;otherModule/BAR&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;bar&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="nl"&gt;default&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;state&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Use custom middlewares
&lt;/h2&gt;

&lt;p&gt;I’ve often seen &lt;code&gt;action&lt;/code&gt; behaviors being copied and pasted, from action to action.When you’re a developer, “copy-paste” is never the right way.&lt;/p&gt;

&lt;p&gt;The most common example is handling HTTP calls during an action that uses &lt;code&gt;redux-thunk&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;foo&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;
  &lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;https://example.com/api/foo&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;FOO&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt; &lt;span class="p"&gt;}))&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;catch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="c1"&gt;// Do something&lt;/span&gt;
    &lt;span class="p"&gt;})&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;bar&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;
  &lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;https://example.com/api/bar&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;BAR&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt; &lt;span class="p"&gt;}))&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;catch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="c1"&gt;// Do something&lt;/span&gt;
    &lt;span class="p"&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;These two actions are basically the same thing, we could very well make a factory that would do the code in common.&lt;/p&gt;

&lt;p&gt;Basically the &lt;em&gt;meta&lt;/em&gt; action we want to represent here when it is &lt;code&gt;dispatched&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;Fetch&lt;/span&gt; &lt;span class="nx"&gt;something&lt;/span&gt;
&lt;span class="o"&gt;--&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;action&lt;/span&gt; &lt;span class="kd"&gt;with&lt;/span&gt; &lt;span class="nx"&gt;the&lt;/span&gt; &lt;span class="nx"&gt;result&lt;/span&gt;
&lt;span class="o"&gt;--&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="nx"&gt;or&lt;/span&gt; &lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="nx"&gt;something&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We could very well define a middleware that would take care of this behavior.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;http&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;store&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;next&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="nx"&gt;action&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;action&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;http&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;action&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;action&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;http&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="c1"&gt;// Do something&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;next&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;action&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// in redux store init&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;exampleApp&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;combineReducers&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;reducers&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;store&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;createStore&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;exampleApp&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nf"&gt;applyMiddleware&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;http&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Thus the two preceding actions could be written much more simpler:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;foo&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;FOO&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;http&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;https://example.com/api/foo&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;bar&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;BAR&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;http&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;https://example.com/api/bar&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The big advantages of using middleware in a complex application:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;avoids code duplication&lt;/li&gt;
&lt;li&gt;allows you to define common behaviors between your actions&lt;/li&gt;
&lt;li&gt;standardize redux &lt;em&gt;meta&lt;/em&gt; action types&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Avoid redux related rerender
&lt;/h2&gt;

&lt;p&gt;The trick when using redux is to trigger component re-render when you connect them to the state. Even if &lt;a href="https://kentcdodds.com/blog/fix-the-slow-render-before-you-fix-the-re-render" rel="noopener noreferrer"&gt;rerenders are not always a problem&lt;/a&gt;, re-render caused by the use of redux really has to be prevented.Just beware of the following traps.&lt;/p&gt;

&lt;h3&gt;
  
  
  Do not create a reference in the &lt;em&gt;selector&lt;/em&gt;
&lt;/h3&gt;

&lt;p&gt;Let’s imagine the next &lt;em&gt;selector&lt;/em&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;getUserById&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;userId&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;state&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;
  &lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;users&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;find&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="nx"&gt;userId&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The developer here wanted to ensure that its &lt;em&gt;selector&lt;/em&gt; is null safe and always returns an &lt;em&gt;object&lt;/em&gt;.This is something we see quite often.&lt;/p&gt;

&lt;p&gt;Each time this selector will be called for a &lt;code&gt;user&lt;/code&gt; not present in the state, it will return a new object, a new reference.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;With useSelector, returning a new object every time will always force a re-render by default.&lt;a href="https://react-redux.js.org/api/hooks#equality-comparisons-and-updates" rel="noopener noreferrer"&gt;Doc of react-redux&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;However in the case of an object, as in the example above (or an array), the reference of this default value is new each time the selector is executed.Similarly for the default values in destructuring, you should never do this :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;getUsers&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;users&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;users&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;What to do then?Whenever possible, the default values should be stored in the reducer.Otherwise, the default value must be extracted into a constant so that the reference remains the same.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;defaultUser&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;getUserById&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;userId&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;state&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;
  &lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;users&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;find&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="nx"&gt;userId&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="nx"&gt;defaultUser&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The same goes for the selector usage that returns a new ref at each call.The use of the &lt;code&gt;filter&lt;/code&gt; function returns a new array each time a new reference even if the filter conditions have not changed.&lt;/p&gt;

&lt;p&gt;To continue, it is important that &lt;a href="https://redux.js.org/recipes/usage-with-typescript#typing-the-useselector-hook" rel="noopener noreferrer"&gt;useSelector&lt;/a&gt; does not return a function.Basically you should never do this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;getUserById&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;state&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;userId&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;
  &lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;users&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;find&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="nx"&gt;userId&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;uider&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useSelector&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;getUserById&lt;/span&gt;&lt;span class="p"&gt;)(&lt;/span&gt;&lt;span class="nx"&gt;userId&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A selector should not return a &lt;em&gt;view&lt;/em&gt; (a copy) of the state but directly what it contains.By respecting this principle, your components will rerender only if an action modifies the state.Utilities such as &lt;a href="https://www.npmjs.com/package/reselect" rel="noopener noreferrer"&gt;reselect&lt;/a&gt; can be used to implement selectors with a memory system.&lt;/p&gt;

&lt;h3&gt;
  
  
  Do not transform your data in the components
&lt;/h3&gt;

&lt;p&gt;Sometimes the data contained in the &lt;code&gt;state&lt;/code&gt; is not in the correct display format.We would quickly tend to generate it in the component directly.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;MyComponent&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useSelector&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;getUser&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;div&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;h1&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/h1&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;img&lt;/span&gt; &lt;span class="nx"&gt;src&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;`https://profil-pic.com/&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/div&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;  &lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here, the url of the image is dynamically computed in the component, and thus at each render.We prefer to modify our reducers in order to include a &lt;code&gt;profileUrl&lt;/code&gt; attribute so that this information is directly accessible.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;switch &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;action&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;type&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="s2"&gt;`user/SET_USER`&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;user&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;action&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;profilUrl&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`https://profil-pic.com/&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;action&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This information is then calculated once per action and not every time it is rendered.&lt;/p&gt;

&lt;h2&gt;
  
  
  Don’t use &lt;em&gt;useReducer&lt;/em&gt; for your business data
&lt;/h2&gt;

&lt;p&gt;Since the arrival of hooks, we have many more tools provided directly by React to manage the state of our components. The &lt;a href="https://fr.reactjs.org/docs/hooks-reference.html#usereducer" rel="noopener noreferrer"&gt;useReducer&lt;/a&gt; hook allows to set a state that can be modified through actions.We’re really very very close to a redux state that we can associate to a component, it’s great.&lt;/p&gt;

&lt;p&gt;However, if you use redux in your application, it seems quite strange to have to use &lt;a href="https://fr.reactjs.org/docs/hooks-reference.html#usereducer" rel="noopener noreferrer"&gt;useReducer&lt;/a&gt;. You already have everything you need to manipulate a complex state.&lt;/p&gt;

&lt;p&gt;Moreover, by using redux instead of the &lt;a href="https://fr.reactjs.org/docs/hooks-reference.html#usereducer" rel="noopener noreferrer"&gt;useReducer&lt;/a&gt; hook you can take advantage of really efficient devtools and middlewares.&lt;/p&gt;




&lt;h2&gt;
  
  
  Useful resources
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://redux.js.org/basics/usage-with-react" rel="noopener noreferrer"&gt;Use react with redux doc&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/reduxjs/redux/issues/653#issuecomment-216844781" rel="noopener noreferrer"&gt;redux flow animated by Dan Abramov&lt;/a&gt; &lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fslashgear.github.io%2F404460ceece985d433e1ed1f36cd4215%2Fredux-flow.gif" alt="redux flow animated by Dan Abramov"&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href="https://redux.js.org/api/applymiddleware" rel="noopener noreferrer"&gt;redux documentation about middlewares&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.npmjs.com/package/immutable-set" rel="noopener noreferrer"&gt;immutable-set&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;em&gt;Thanks to the reviewers:&lt;a href="https://github.com/flepretre" rel="noopener noreferrer"&gt;@flepretre&lt;/a&gt;,&lt;a href="https://github.com/mfrachet" rel="noopener noreferrer"&gt;@mfrachet&lt;/a&gt;,&lt;a href="https://github.com/fdubost" rel="noopener noreferrer"&gt;@fdubost&lt;/a&gt;,&lt;a href="https://github.com/ncuillery" rel="noopener noreferrer"&gt;@ncuillery&lt;/a&gt;,&lt;a href="https://github.com/renaudAmsellem" rel="noopener noreferrer"&gt;@renaudAmsellem&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>react</category>
      <category>redux</category>
    </item>
  </channel>
</rss>
