Skip to main content

JavaScript defines the behavior and interaction of the application.

Introduction

JavaScript is the foundation of the logic of our applications. It is important to follow best practices and consistent patterns whether using something that compiles to it, like TypeScript, or a framework, like React.

  • JavaScript should be valid
    • No console errors
  • JavaScript should be DRY
    • Be reusable whenever possible
  • JavaScript should be unobtrusive, fast, efficient, and performant
    • Included after careful consideration
    • Executed only when necessary
    • Evaluated for performance overhead, file size, and maintainability
    • Performs only the necessary tasks without needless overhead
    • Does not contain HTML, CSS, or hard-coded text content
      • Writing HTML in a JavaScript file makes the content harder to find, harder to edit, and less performant
      • Keep text content external for translations and content management
  • JavaScript should be scoped appropriately
    • Minimize the use of globally scoped variables
    • Use const and let when declaring variables for better scoping and error messaging

Naming conventions

  • All names should be semantic
  • All names in global or shared code must be abstract and reusable
  • Function and variable names should be descriptive of what they do or represent
  • Boolean values should be prefixed with "is" whenever possible
  • Use a last-name-first approach to naming, e.g.: "NavPrimary"

Comments

  • Write self-explanatory or "self-commenting" code supplemented by code comments
  • Explain what a JavaScript file does at the top of the file
  • Explain what a function does, and make note of required parameters and their types using the JSDoc standard
  • Explain any segments of code that could come across as confusing
  • Mark TODOs and action items with a TODO comment and a ticket number

Organization

JavaScript should exist in its own file and be imported into the document via a <script> tag at the bottom of the body. Some cases may require it to be imported in the head instead.

Vanilla

JavaScript should be used sparingly. Any and all JavaScript code should be included if, and only if, it is needed for the page to achieve the desired ends, e.g.: when a behavior or interaction cannot be achieved with HTML or CSS alone.

  • Use closures or object literals to avoid global scope
  • Carefully consider the impact of the absence or failure of the code
    • What happens if for some reason this code is missing or does not run?
    • What happens if the code triggers an error?

TypeScript

Components and props

  • Components should have a return type of JSX.Element
  • Props should be typed with a "Props" interface

Typing

  • Extend existing types and native elements whenever possible to keep code DRY

React

React is a powerful tool that — when used correctly — provides scalability, speeds up development, and improves the development experience. It has thorough documentation and strong community support. React has the highest retention and usage of any front-end framework, making it the safest technology to adopt. And it continues to be the best framework to attract, retain, and grow developer talent.

  • When conditionally adding a value to an optional attribute, ensure the condition returns undefined
  • Use function components with hooks
    • Function based components reduce the size of the application shipped to the user by only importing what is used
  • If using React 18 or newer, use the built-in useId() when generating unique IDs

Components

A component is a piece of an application that follows the single responsibility principle and completes a single task. Any shared or reusable code should be pulled into a separate component and stored in a shared directory within the application’s architecture.

State

  • Use state to store values that are rendered in markup or to effect values that are rendered in markup
  • Optimize code to reduce the number of re-renders
    • Limit state updates using useEffect, useCallback, and useMemo
    • Use Context to elevate state that is shared between components instead of passing values up and down the tree

Props

  • Avoid destructuring props
    • Keeping the props in the props object increases readability of code and knowledge of where the data is coming from
    • There are cases when destructuring props is necessary to intercept and override values
  • <p>{props.text}</p> indicates the data is coming from outside the component
  • <p>{text}</p> indicates the data is coming from within the component

Routing

  • Use routing when developing an application with multiple pages
    • Each page should have its own unique route
    • Maintain the browser history to ensure the browser's forward and back buttons operate as expected

Organization

Following a consistent structure makes navigating a component’s code easier for developers who are familiar with the component and developers who are looking at it for the first time.

When structuring components, use the following order:

  • Imports
  • Interfaces
    • Props should be the last interface
  • Component
    • Hooks using external data, e.g.: useLocation()
    • State
    • Refs
    • Functions and hooks using internal data
    • UseEffects
    • Return statement

Additional resources