dirty sneaker

This commodity will focus on make clean code practices as they apply to modern React software development. I'll also talk about some of the "sugar" that ES6/ES2015 brings to the tabular array.

What is clean code, and why do I care?

Clean code is a consequent manner of programming that makes your code easier to write, read, and maintain. Often a developer spends time on a problem, and one time the problem is solved, they make a pull request. I fence that yous aren't washed just because your code "works."

Now is your chance to make clean it upwards by removing dead code (zombie lawmaking), refactoring, and removing whatever commented-out code! Strive for maintainability. Ask yourself, "Will someone else be able to empathize this code six months from now?"

In simpler terms, write code that you lot would be proud to take home and bear witness your mother.

Why practice you intendance? Because if you're a skilful developer, you're lazy. Hear me out – I mean that every bit a compliment. A good developer, when faced with a situation where they have to do something more than in one case, volition generally notice an automated (or better) solution to complete the chore at hand. So considering you're lazy, subscribing to clean-code techniques will decrease the frequency of changes from pull-request code reviews and the need to come back to the same slice of code over and over.

Clean code passes the "smell examination"

Clean code should pass the scent exam. What do I mean by that? We've all looked at code (our own or others') and said, "Something'due south not quite right here." Remember, if it doesn't feel right, it probably isn't. Code that's well thought out just comes together. If it feels like yous're trying to fit a square peg into a round hole, then pause, step back, and have a suspension. Nine times out of 10, you'll come up with a meliorate solution.

Clean lawmaking is Dry

Dry is an acronym that stands for "Don't Echo Yourself." If you are doing the same thing in multiple places, consolidate the duplicate lawmaking. If you lot see patterns in your code, that is an indication it is prime for DRYing. Sometimes this means continuing back from the screen until you can't read the text and literally looking for patterns.

                          // Dirty              const              MyComponent              =              ()              =>              (              <              div              >              <              OtherComponent              type              =              "a"              className              =              "colorful"              foo              =              {              123              }              bar              =              {              456              }              /              >                            <              OtherComponent              type              =              "b"              className              =              "colorful"              foo              =              {              123              }              bar              =              {              456              }              />                                                        <              /div              >                            );                      
                          // Clean              const              MyOtherComponent              =              ({              type              })              =>              (              <              OtherComponent              type              =              {              type              }              className              =              "colorful"              foo              =              {              123              }              bar              =              {              456              }              /              >                            );              const              MyComponent              =              ()              =>              (              <              div              >              <              MyOtherComponent              type              =              "a"              />              <              MyOtherComponent              blazon              =              "b"              />              <              /div              >                            );                      

Sometimes – every bit in our instance above – DRYing your code may actually increase code size. Still, DRYing your code also generally improves maintainability.

Be warned that information technology's possible to become likewise far with DRYing up your lawmaking, so know when to say when.

Clean lawmaking is anticipated and testable

Writing unit of measurement tests is non just a adept idea, it's become virtually mandatory. Afterwards all, how can you lot be sure that your latest shiny new feature didn't introduce a problems somewhere else?

Many React developers rely on Jest for a cipher-configuration test runner and to produce code coverage reports. And if yous're interested in visual earlier/after comparison testing, please check out American Express's own Jest Image Snapshot.

Has this happened to you before? Yous wrote some code and made certain that it was fully commented. Every bit will happen, you establish a bug, so yous went dorsum and changed the code. Did you remember to change your comments as well to reflect the new logic? Maybe. Perhaps non. The next person who looked at your code and so may have gone down a rabbit hole because they focused on the comments.

Add comments only to explain complex thoughts; that is, don't annotate on the obvious. Fewer comments also reduces visual clutter.

                          // Dingy              const              fetchUser              =              (              id              )              =>              (              fetch              (              buildUri              `              /              users              /              $              {              id              }              `              )              // Become User DTO record from REST API              .              then              (              convertFormat              )              // Convert to snakeCase              .              then              (              validateUser              )              // Brand sure the the user is valid              );                      

In the make clean version, we rename some of the functions to better depict what they exercise, thus eliminating the need for comments and reducing visual clutter. This limits the potential confusion of the code not matching the comments subsequently.

                          // Make clean              const              fetchUser              =              (              id              )              =>              (              fetch              (              buildUri              `              /              users              /              $              {              id              }              `              )              .              then              (              snakeToCamelCase              )              .              then              (              validateUser              )              );                      

Naming things

In my previous article Part as Child Components Are an Anti-Pattern, I stressed the importance of naming things. We should all give serious thought to variable names, function names, and even filenames.

Hither are a few guidelines:

  • Boolean variables, or functions that return a boolean value, should first with "is," "has" or "should."

                                      // Dirty                  const                  done                  =                  current                  >=                  goal                  ;                              
                                      // Make clean                  const                  isComplete                  =                  current                  >=                  goal                  ;                              
  • Functions should be named for what they do, not how they do information technology. In other words, don't expose details of the implementation in the name. Why? Considering how you practise information technology may change some mean solar day, and you shouldn't need to refactor your consuming lawmaking because of it. For case, you may load your config from a REST API today, but you may make up one's mind to broil information technology into the JavaScript tomorrow.

                                      // Dirty                  const                  loadConfigFromServer                  =                  ()                  =>                  {                  ...                  };                              
                                      // Clean                  const                  loadConfig                  =                  ()                  =>                  {                  ...                  };                              

Make clean code follows proven design patterns and best practices

Computers accept been effectually a long time. Throughout the years, programmers discovered patterns in the manner they solved certain problems. These are called design patterns. In other words, there are algorithms that have been proved over time to work, so you should stand up on the shoulders of those who preceded yous so that you don't have to brand the same mistakes.

Then there are best practices. They are similar to pattern patterns but broader, not specific to a coding algorithm. They might cover things like, "Y'all should lint your code" or "When writing a library packet, include React as a peerDependency."

Here are some best practices to follow when architecting your React applications.

  • Use small-scale functions, each with a single responsibleness. This is called the single responsibility principle. Ensure that each role does one job and does it well. This could mean breaking up circuitous components into many smaller ones. This also volition lead to amend testability.

  • Be on the lookout for leaky abstractions. In other words, don't impose your internal requirements on consumers of your code.

  • Follow strict linting rules. This will help y'all write clean, consistent code.

Make clean code doesn't (necessarily) take longer to write

I hear the statement all the fourth dimension that writing clean code volition slow productivity. That's a bunch of hooey. Yes, initially you may need to deadening down earlier you lot can speed up, but eventually your pace will increase as you are writing fewer lines of code.

And don't disbelieve the "rewrite factor" and fourth dimension spent fixing comments from code reviews. If you suspension your lawmaking into small modules, each with a unmarried responsibility, it's likely that yous'll never have to touch on most modules again. There is time saved in "write it and forget it."

Applied examples of dirty code vs. make clean lawmaking

DRY upwards this code

Take a look at the code sample below. Go ahead and pace back from your monitor every bit I described above. Practise you lot meet any patterns? Notice that the component Thingie is identical to ThingieWithTitle with the exception of the Title component. This is a perfect candidate for DRYing.

                          // Dirty              import              Title              from              './Title'              ;              export              const              Thingie              =              ({              clarification              })              =>              (              <              div              class              =              "thingie"              >              <              div              class              =              "clarification-wrapper"              >              <              Description              value              =              {              description              }              /              >                            <              /div              >                            <              /div              >                            );              export              const              ThingieWithTitle              =              ({              title              ,              description              })              =>              (              <              div              >              <              Championship              value              =              {              title              }              /              >                            <              div              class              =              "description-wrapper"              >              <              Description              value              =              {              description              }              /              >                            <              /div              >                            <              /div              >                            );                      

Hither we've allowed the passing of children to Thingie. Nosotros've and then created ThingieWithTitle that wraps Thingie, passing in the Title every bit its children.

                          // Clean              import              Title              from              './Championship'              ;              export              const              Thingie              =              ({              clarification              ,              children              })              =>              (              <              div              class              =              "thingie"              >              {              children              }              <              div              grade              =              "description-wrapper"              >              <              Description              value              =              {              description              }              /              >                            <              /div              >                            <              /div              >                            );              export              const              ThingieWithTitle              =              ({              title              ,              ...              others              })              =>              (              <              Thingie              {...              others              }              >              <              Title              value              =              {              title              }              /              >                            <              /Thingie              >                            );                      

Default values

Take a look at the following code snippet. It defaults the className to "icon-large" using a logical OR statement, similar to the way your grandfather might have done it.

                          // Dirty              const              Icon              =              ({              className              ,              onClick              })              =>              {              const              additionalClasses              =              className              ||              'icon-big'              ;              return              (              <              span              className              =              {              `              icon              -              hover              $              {              additionalClasses              }              `              }              onClick              =              {              onClick              }              >              <              /span              >                            );              };                      

Here we use ES6's default syntax to supervene upon undefined values with empty strings. This allows us to utilize ES6's single statement form of the fat-arrow function, thus eliminating the demand for the return statement.

                          // Clean              const              Icon              =              ({              className              =              'icon-big'              ,              onClick              })              =>              (              <              bridge              className              =              {              `              icon              -              hover              $              {              className              }              `              }              onClick              =              {              onClick              }              /              >                            );                      

In this even cleaner version, the default values are set in React.

                          // Cleaner              const              Icon              =              ({              className              ,              onClick              })              =>              (              <              bridge              className              =              {              `              icon              -              hover              $              {              className              }              `              }              onClick              =              {              onClick              }              /              >                            );              Icon              .              defaultProps              =              {              className              :              'icon-big'              ,              };                      

Why is this cleaner? And is it really amend? Don't all three versions exercise the aforementioned thing? For the most part, yes. The reward of letting React prepare your prop defaults, nevertheless, is that it produces more efficient code, defaults props in a Class based lifecycle component, as well as allows your default values to be checked confronting propTypes. But at that place is one more reward: it declutters the default logic from that of the component itself.

For example, you could do the following, storing all of your default props in one identify. I'm not suggesting that you lot practise; I'yard merely saying that you lot have the flexibility to do so.

                          import              defaultProps              from              './defaultProps'              ;              ...              Icon              .              defaultProps              =              defaultProps              .              Icon              ;                      

Separate stateful aspects from rendering

Mixing your stateful data-loading logic with your rendering (or presentation) logic tin lead to component complication. Instead, write a stateful container component whose single responsibility is to load the data. And then write some other component whose sole responsibleness is to display the data. This is called the Container Pattern.

In the example beneath, user information is loading and is displayed in a unmarried component.

                          // Muddy              class              User              extends              Component              {              state              =              {              loading              :              truthful              };              render              ()              {              const              {              loading              ,              user              }              =              this              .              state              ;              render              loading              ?              <              div              >              Loading              ...              <              /div              >                            :              <              div              >              <              div              >              First              name              :              {              user              .              firstName              }              <              /div              >                            <              div              >              First              proper name              :              {              user              .              lastName              }              <              /div              >                            ...              <              /div>              ;                            }              componentDidMount              ()              {              fetchUser              (              this              .              props              .              id              )              .              and then              ((              user              )              =>              {              this              .              setState              ({              loading              :              imitation              ,              user              })})              }              }                      

In the clean version, the concerns – loading information, displaying a loading spinner, and displaying data – have been separated. Not merely does this brand the lawmaking easier to understand, only testing will require a lot less effort as y'all can examination each business organisation independently. And because RenderUser is a stateless functional component, the results are predictable.

                          // Clean              import              RenderUser              from              './RenderUser'              ;              grade              User              extends              Component              {              country              =              {              loading              :              true              };              render              ()              {              const              {              loading              ,              user              }              =              this              .              state              ;              return              loading              ?              <              Loading              />              :              <              RenderUser              user              =              {              user              }              />              ;                            }              componentDidMount              ()              {              fetchUser              (              this              .              props              .              id              )              .              and then              (              user              =>              {              this              .              setState              ({              loading              :              false              ,              user              })})              }              }                      

Use stateless functional components

Stateless functional components (SFCs) were introduced in React v0.14.0, and they are used to profoundly simplify a render-only component. Simply some developers oasis't allow go of the past. For example, the post-obit component is ripe for converting to an SFC.

                          // Muddy              class              TableRowWrapper              extends              Component              {              render              ()              {              return              (              <              tr              >              {              this              .              props              .              children              }              <              /tr              >                            );              }              }                      

The make clean version clears a lot of the screen clutter of the muddied version. Through optimization of React'southward core, information technology's possible to use far less retentivity, as no instance is created.

                          // Clean              const              TableRowWrapper              =              ({              children              })              =>              (              <              tr              >              {              children              }              <              /tr              >                            );                      

Remainder/spread

About a twelvemonth agone, it was my conventionalities that Object.assign would become anybody's new best friend. Well times accept changed. Enter the rest/spread spec in ES2016/ES7.

Accept the case where you pass some props to a component. You'd like to apply className in the component itself, only pass all other props down the concatenation. You lot would do something like this.

                          // Dirty              const              MyComponent              =              (              props              )              =>              {              const              others              =              Object              .              assign              ({},              props              );              delete              others              .              className              ;              render              (              <              div              className              =              {              props              .              className              }              >              {              React              .              createElement              (              MyOtherComponent              ,              others              )}              <              /div              >                            );              };                      

Not a very elegant solution, is it? But with rest/spread, it's a piece of block!

                          // Make clean              const              MyComponent              =              ({              className              ,              ...              others              })              =>              (              <              div              className              =              {              className              }              >              <              MyOtherComponent              {...              others              }              /              >                            <              /div              >                            );                      

We take the "rest" of the properties and we "spread" them every bit new props to MyOtherComponent. (Sometimes things just name themselves…)

Destructure when applicable

ES6 introduced the concept of destructuring, which really is your best friend. Destructuring allows you lot to "pull apart" properties of an object or elements of an array.

Object destructuring

In this example, componentWillReceiveProps is passed newProps, and we set state.active to the new active prop.

                          // Dirty              componentWillReceiveProps              (              newProps              )              {              this              .              setState              ({              active              :              newProps              .              active              });              }                      

In this make clean version, we destructure newProps into agile. Not simply do nosotros no longer need to reference newProps.agile, but nosotros too tin can use ES6 object property shorthand in setState.

                          // Make clean              componentWillReceiveProps              ({              agile              })              {              this              .              setState              ({              active              });              }                      

Array destructuring

An frequently overlooked ES6 feature is array destructuring. Take the following lawmaking for case. It takes in a locale such as "en-US" and breaks it into language (en) and country (US).

                          // Muddied              const              splitLocale              =              locale              .              carve up              (              '-'              );              const              language              =              splitLocale              [              0              ];              const              country              =              splitLocale              [              1              ];                      

In the make clean version, ES6 has you covered.

                          // Clean              const              [              language              ,              country              ]              =              locale              .              split              (              '-'              );                      

In determination…

I hope that I've helped you meet the benefits of writing clean code and that yous tin can even use some of the practical examples presented here. Once you embrace writing clean code, information technology volition get 2d nature. Yous (and your hereafter self) will before long appreciate the "write it and forget it" way of life.