---
# System prepended metadata

title: "\U0001F304 Utopian React App"

---

# 🌄 Utopian React App

This doctrine is a collection of experienced approaches to authoring a React app.

## General Rules

1. 🚨 [Only use named exports](https://dev.to/n8io/developer-dark-arts-default-exports-31ia)
2. 📤 Only `export` at the end of a file. Do not sprinkle them throughout the module like Hansel and Gretel.
3. 🚨 Only use arrow functions
4. 👩‍🎓 Only use functional React components. [Death to class components](https://dev.to/n8io/developer-dark-arts-react-class-components-3g8j). 
5. 🧪 Spec files should be colocated to the implementation (and suffixed with `.spec.tsx`)
    * No `__tests__` directories
    * No `.test.tsx` suffix
6. 📤 Only export from a module when there is a use case
7. 🏷️ Import types via `import type { } from ...` syntax when possible
8. 🗄️ If a component/data/util is used by multiple parents, move it up to a common parent directory
9. 🎣 All data requests should be made via `hook`
10. 👷‍♂️ Shared state should be shared via `Context` and accessed via `hook`
11. 🐫 React components should always be in the form of a `ProperCased` directory with child `index.tsx` and `index.spec.tsx` files
    * _All other file & directory names and should be `camelCased`_
12. 🥇 React component files should contain only one component. Large components are fragile and hard to test.
13. 🔗 You should always use a `react-router-dom` `<Link/>` for all links
14. ⨱ A variable name should never start with an underscore (`_`). The exception being that you want to keep an unused, positional function parameter as a placeholder to maintain readability.
    ```typescript=
    // For example...
    const removeUserMiddleware = (_request, response, next) => {
      response.body.user = undefined
      next()
    }
    ```
11. 🔡 [Alphasort all the things](https://dev.to/n8io/developer-dark-arts-ralpha-sorting-c0o): destructured object keys, component props, imports, enum values, oh my! _If we have our linting/styling setup properly these will sort automatically when saving a file_
12. 🧶 [No magic strings/numbers](https://dev.to/n8io/developer-dark-arts-magic-strings-2ihn). These should be contained in an aptly-named variable(s) prior to consuming them.

## Testing

### Unit Tests

1. We should aim for 80% coverage
2. There should only be one snapshot test and it should be representative of the happy path of a component. Other conditional rendering should be tested using other means. E.g. `data-testid`'s or triggering events.
3. Snapshot tests should be inlined (via `.toMatchInlineSnapshot()`) _AND_ short (less than ~100 lines) 
4. Where possible, child components should be mocked
    * Reduces the snapshot size
    * Promotes separation of concerns
    * Focuses tests to the given component's unit of work

### End to End Tests

In an ideal world, **a feature should have at least one test**, possibly many more depending on its complexity. Good E2E tests should be checking if a particular set of interactions has a resulting outcomes that cannot be tested reliably by unit test. Their pass/fail outcome should answer the question "Is this feature working as expected?"

## Project Structure

### 🗃️ Root Directories

#### `components`

The place for React components that are shared across multiple modules. One directory per component, possibly with nested child components.

#### `constants`

Where you will find `enum`'s and frozen objects that are shared across multiple modules. One file per.

#### `hooks`

Where you will find all hooks that are shared across multiple modules. One directory per.

#### `modules`

1. Each module directory represents an app page/view (excluding `App`)
2. Each module should have a `Routes/index.tsx` that controls top level and child routing
   1. This is where you might see child route lazy loading if needed
3. Each module should export, at minimum, the `Routes` component

Note: A general rule of thumb, if it is used across multiple modules, it needs to be elevated to a top level directory

##### The `modules/App` Directory

This special module is needed to setup top level providers, contexts, styles, routing, and config. It is the entry point of the React app.

#### `types`

A place for types that are shared across multiple modules. One file per _logical model_. Multiple types can live in a single file so long as they share the same model/namespace. 

_NOTE: Don't forget, `enum`'s should live in `constants`_

#### `utils`

The home of shared utility functions that are shared across multiple modules. One directory per.

### 🚸 Child Directories

Common child directories you _might_ see in `components` and `modules` root directories...

1. `components`
2. `constants`
3. `hooks`
4. `types`
5. `utils`
6. `Routes` - The component that controls nested view routing

Note: These directories should only contain items that are scoped to the given module/component

### Import Aliases and Relative Pathing

As a convenience, most projects allow aliased imports to avoid import statements with runaway relative paths.

```typescript=
// ❌
import { thing } from '../../../../omg/make/it/stop/util/thing'

// ✅
import { thing } from 'util/thing'
```

While this makes things much more readable, you can get yourself into trouble if you're not careful.

#### TLDR; 
* If you are importing something **within** the current module, use the relative path (e.g. `'../../../util/thing'`). 
* If you are importing something **outside** the current module, use the aliased path (e.g. `'util/thing'`)

#### The Long Story

The `modules` root directory is a logical boundary between the "public apis" of each module. Each module's `index.tsx` should define all that is publicly accessible.

```typescript=
// Given this...

// modules/otherModule/util/index.tsx
const util = () = '🚀'
export { util }

// modules/otherModule/index.tsx
export { util } from './util'
```

```typescript=
// ❌ Don't do this
// modules/moduleA/Thing/index.tsx
import { util } from 'modules/otherModule/util'
```

```typescript=
// ✅ Do this instead
// modules/moduleA/Thing/index.tsx
import { util } from 'modules/otherModule'
```

There are a few reasons why we would choose to follow this convention.

1. At a glance it should be easy to know what other modules might be using from the current module by simply opening up the module's `index.tsx` and reviewing the `export`'s therein.
2. Implicitly this helps us avoid and/or identify circular dependencies when they occur. 
    * For example, `moduleC => depends on moduleB => depends on moduleA => depends on moduleC` is easier to reason about when there is a single entry point for each `module`
    * Circular dependencies are notoriously difficult to troubleshoot and can be easily avoided when we follow this rule.