We use cookies and other tracking technologies to improve your browsing experience on our site, analyze site traffic, and understand where our audience is coming from. To find out more, please read our privacy policy.

By choosing 'I Accept', you consent to our use of cookies and other tracking technologies.

We use cookies and other tracking technologies to improve your browsing experience on our site, analyze site traffic, and understand where our audience is coming from. To find out more, please read our privacy policy.

By choosing 'I Accept', you consent to our use of cookies and other tracking technologies. Less

We use cookies and other tracking technologies... More

Login or register
to apply for this job!

Login or register to start contributing with an article!

Login or register
to see more jobs from this company!

Login or register
to boost this post!

Show some love to the author of this blog by giving their post some rocket fuel 🚀.

Login or register to search for your ideal job!

Login or register to start working on this issue!

Engineers who find a new job through JavaScript Works average a 15% increase in salary 🚀

Blog hero image

Clean Code in React

David Feng 23 February, 2018 | 4 min read

My first full stack project is Bara, a single-page Yelp clone. After weeks of development and refactoring, I am pretty happy with the result. The UI looks good; the functionality works fine: users can sign up, log in, CRUD businesses and reviews.

1_d4twnONZVk9EvglgOlp01g.png

Recently I’ve been reading Clean Code, and I begin to appreciate the importance of keeping the code clean. Programmers are authors; the code is like books we write, except our reader almost never begin to read from page 1. Usually the reader directly dives into a module/component to fix a problem or add a feature. To help the reader (could be your teammate, or even future you!), it is the author’s responsibility to make sure that the code is easy to read (and to change, but that’s another big topic). Martin Fowler said:

Any fool can write code that a computer can understand. Good programmers write code that humans can understand.

I decided to refactor Bara as a practice. The code works (the computer understands it), but it’s not clean. I did not intentionally make my code hard to read; I took care of indentations and whitespaces, but that code was far from clean. For example, the Home component, which renders the homepage, looked like this:

import React from 'react';
import {
  fetchFeaturedBusinesses
} from '../../util/business_api_util';

import HomeBarContainer from './home_bar_container';
import SearchBar from '../header/search_bar';
import HomeLinks from './home_links';
import {
  FeaturedBusinesses,
  Categories
} from './home_util';

export default class Home extends React.Component {
  constructor( props ) {
    super( props );
    this.state = {
      defaultBackground: true,
      loading: true,
      businesses: [],
    };

    this.handleClick = this.handleClick.bind( this );
  }

  componentDidMount() {
    this.handleClick();
  }

  handleClick() {
    fetchFeaturedBusinesses()
      .then( ( businesses ) => {
        this.setState( prevState => ( {
          loading: false,
          businesses,
          defaultBackground: !prevState.defaultBackground
        } ) );
      } );
  }

  homeHero() {
    let homeHeroContent = (
      <div>
        <HomeBarContainer />
        <div className='logo' onClick={this.handleClick}>
          <img src={window.staticImages.homeLogo} />
        </div>
        <div className='home-search'>
          <SearchBar />
        </div>
        <HomeLinks />
      </div>
    );
    return (
      <div
        className={this.state.defaultBackground
          ? 'home-header-1'
          : 'home-header-2'}
      >
        {homeHeroContent}
      </div>
    );
  }

  featuredBusinesses() {
    return this.state.loading ?
      <img className='spinner' src={window.staticImages.spinner} /> :
      <FeaturedBusinesses businesses={this.state.businesses} />;
  }

  render() {
    return (
      <div>
        {this.homeHero()}
        <div className='center'>
          {this.featuredBusinesses()}
        </div>
        <Categories />
      </div>
    );
  }
}

The Home component has three parts. From top to bottom, they are: 1. HomeHero, which contains the HomeBarContainer (login and signup links), the logo, the SearchBar, and HomeLinks; 2. FeaturedBusinesses, which is just three random businesses; 3. Categories, which contains links to different businesses based on their categories. The core functionality of this page is that clicking on the logo changes FeaturedBusinesses and the background image of HomeHero.

However, if my code were cleaner, not a single word in the previous paragraph would be necessary. The code can (and should) tell you what it does, explicitly, in a human-friendly way.

import React from 'react';
import {
  fetchFeaturedBusinesses
} from '../../util/business_api_util';
import HomeHero from './home_hero';
import FeaturedBusinesses from './featured_businesses';
import Categories from './categories';

export default class Home extends React.Component {
  constructor( props ) {
    super( props );
    this.state = {
      showDefaultBackground: true,
      loading: true,
      featuredBusinesses: [],
    };

    this.handleHomeLogoClick = this.handleHomeLogoClick.bind( this );
    this.saveFeaturedBusinesses = this.saveFeaturedBusinesses.bind( this );
    this.updateHomeHeroBackground = this.updateHomeHeroBackground.bind( this );
  }

  componentDidMount() {
    this.fetchAndSaveFeaturedBusinesses();
  }

  handleHomeLogoClick() {
    this.fetchAndSaveFeaturedBusinesses();
    this.updateHomeHeroBackground();
  }

  fetchAndSaveFeaturedBusinesses() {
    fetchFeaturedBusinesses()
      .then( featuredBusinesses => {
        this.saveFeaturedBusinesses( featuredBusinesses );
      } );
  }

  saveFeaturedBusinesses( featuredBusinesses ) {
    this.setState( {
      loading: false,
      featuredBusinesses,
    } );
  }

  updateHomeHeroBackground() {
    this.setState( prevState => ( {
      showDefaultBackground: !prevState.showDefaultBackground
    } ) );
  }

  render() {
    return (
      <div>
        <HomeHero
          handleHomeLogoClick={this.handleHomeLogoClick}
          showDefaultBackground={this.state.showDefaultBackground}
        />
        <FeaturedBusinesses
          businesses={this.state.featuredBusinesses}
          loading = {this.state.loading}
        />;
        <Categories />
      </div>
    );
  }
}

Here’s what I did to make the code cleaner:

Break down the component: only one level of abstraction per component. The render method returns the three subcomponents: HomeHero, FeaturedBusinesses, and Categories.

Initially I only created Categories component since it’s static, while HomeHero has a handleClick callback, and FeaturedBusinesses has some extra logic. However, I can pass those information to the children as props, and this greatly cleans up the render method. The Home component does not have to know SearchBar or HomeBarContainer, let HomeHero take care of those.

Break down the function: only one level of abstraction per function. For example, the original handleClick does several things: it fetches featured businesses from the backend, saves them in the local state, and changes the background of HomeHero.

I group the first two things together since there is a logic connection between them, while changing the background is a totally separate issue. Therefore in the new handleHomeLogoClick function, I call two functions to take care of each of them: 1. fetch and save featured functions; 2. update HomeHero's background. Of course the first function can be further broken down.

The one level of abstraction rule gives the reader an option to ignore implementation details if he/she does not care. Overall, the logic is much more explicit, making the code less error-prone. Actually, after this refactoring, I found that in my old version of componentDidMount, I shouldn’t update HomeHero's background. In the new structure this bug becomes pretty obvious.

Use more descriptive names. The functions I mentioned in last section were named as fetchAndSaveFeaturedBusinesses, saveFeaturedBusinesses, updateHomeHeroBackground, etc. Moreover, in the local state, businesses field was renamed to featuredBusinesses, and handleClick function was renamed to handleHomeLogoClick. The extra information makes the code easier to understand (for humans!).

Conclusion: Write clean code. Your teammate and future you will thank you later. If you find this post interesting, make sure to check out Clean Code by Uncle Bob (disclaimer: I am not getting paid by anyone for doing this).

If you’re passionate about Front End development, check out the JavaScript Works job-board here.

Originally published on codeburst.io

Related Jobs

Related Issues

viebel / klipse-clj
viebel / klipse-clj
  • Open
  • 0
  • 0
  • Intermediate
  • Clojure
viebel / klipse
  • Open
  • 0
  • 0
  • Intermediate
  • Clojure
viebel / klipse
  • Open
  • 0
  • 0
  • Intermediate
  • Clojure
  • $100
viebel / klipse
  • 1
  • 0
  • Intermediate
  • Clojure
viebel / klipse
  • Open
  • 0
  • 0
  • Intermediate
  • Clojure
  • $80
viebel / klipse
  • Open
  • 0
  • 0
  • Advanced
  • Clojure
  • $80
viebel / klipse
  • Started
  • 0
  • 2
  • Advanced
  • Clojure
  • $180
viebel / klipse
  • Open
  • 0
  • 0
  • Intermediate
  • Clojure
viebel / klipse
  • Started
  • 0
  • 1
  • Intermediate
  • Clojure
  • $80

Get hired!

Sign up now and apply for roles at companies that interest you.

Engineers who find a new job through JavaScript Works average a 15% increase in salary.

Start with GithubStart with Stack OverflowStart with Email