14 Beneficial Tips to Write Cleaner Code in React Apps
Tags: react, javascript, node, webdev
Published: 2019-08-18 14:26:18

Find me on [medium](https://medium.com/@jsmanifest)

Writing clean code is something that becomes mandatory at some point in your career especially while you're trying to obtain your first developer job. It's essentially what makes you a team player and can either break or make your success from a job interview. How you write code is one of the things they want to look at before making the hiring decision. Your code should be understandable by humans and not just by a machine.

The things listed in this article should apply more importantly the bigger your project becomes and _might_ not be necessary for smaller ones. Just use your best judgment :)

Here are 14 Beneficial Tips to Write Cleaner Code in React Apps:

## 1. Destructure Your Props

Destructuring your props is a good way to help make your coder cleaner and more maintainable. That's because you clearly define or declare what something (like a component) is using and it doesn't force developers to read through the implementation of the component to find out all the props that are tied to the component.

It also gives you the ability to declare default values for them which you've probably seen plenty of times:

```jsx
import React from 'react'
import Button from 'components/Button'

const MyComponent = ({ placeholder = '', style, ...otherProps }) => {
  return (
    <Button
      type="button"
      style={{
        border: `1px solid ${placeholder ? 'salmon' : '#333'}`,
        ...style,
      }}
      {...otherProps}
    >
      Click Me
    </Button>
  )
}

export default MyComponent
```

One of the coolest things I find about destructuring in JavaScript is that it lets you support different variations of parameters.

For example, if you had an _authenticate_ function that used to taken in a `token` as a parameter to authenticate users and now wish to take in `jwt_token` because of a new server response structure, you can easily support both parameters without changing much of your code:

```jsx
// before refactoring
async function authenticate({ user_id, token }) {
  try {
    const response = await axios.post('https://someapi.com/v1/auth/', {
      user_id,
      token,
    })
    console.log(response)
    return response.data
  } catch (error) {
    console.error(error)
    throw error
  }
}

// after refactoring
async function authenticate({ user_id, jwt_token, token = jwt_token }) {
  try {
    const response = await axios.post('https://someapi.com/v1/auth/', {
      user_id,
      token,
    })
    console.log(response)
    return response.data
  } catch (error) {
    console.error(error)
    throw error
  }
}
```

`jwt_token` will be evaluated by the time the code gets to `token`, so if `jwt_token` is a valid token and `token` is `undefined`, then the value of `token` will become the value of `jwt_token`. If the `token` was already some truthy value (a real token), it will just keep itself.

## 2. Folderize Your Components

Lets take a look at this directory structure below:

- src
  - components
    - Breadcrumb.js
    - CollapsedSeparator.js
    - Input
      - index.js
      - Input.js
      - utils.js
      - focusManager.js
    - Card
      - index.js
      - Card.js
      - CardDivider.js
    - Button.js
    - Typography.js

Breadcrumbs are commonly known to be associated with some sort of separator as one of their core functionalities. The `CollapsedSeparator` component is imported inside `Breadcrumb.js`, so we know that they are both related in implementation. However, someone who doesn't know this information might assume that `Breadcrumb` and `CollapsedSeparator` are two completely separate components that are not related to each other at all--especially if `CollapsedSeparator` does not have any clear indications of it being related to a breadcrumb like having the prefix _Breadcrumb_ (BreadcrumbCollapsedSeparator.js) for example.

Since we know that they are related we'd probably question why they aren't in a folder like Input and Card is doing and start to make weird possible assumptions like "I wonder if someone put it there to see if I would take it out like a good samaritan...". The effects of clean code practices should be the opposite--developers should be able to read your code and understand the situation in a snap!

_Folderizing_ the breadcrumb looks something like this:

- src
  - components
    - Breadcrumb
      - index.js
      - Breadcrumb.js
      - CollapsedSeparator.js
    - Input
      - index.js
      - Input.js
      - utils.js
      - focusManager.js
    - Card
      - index.js
      - Card.js
      - CardDivider.js
    - Button.js
    - Typography.js

Now no matter how many _Breadcrumb_ related components are created after that, we will _always_ know that they are related to `Breadcrumb` as long as they reside in the same directory:

- src
  - components
    - Breadcrumb
      - index.js
      - Breadcrumb.js
      - CollapsedSeparator.js
      - Expander.js
      - BreadcrumbText.js
      - BreadcrumbHotdog.js
      - BreadcrumbFishes.js
      - BreadcrumbLeftOvers.js
      - BreadcrumbHead.js
      - BreadcrumbAddict.js
      - BreadcrumbDragon0814.js
      - BreadcrumbContext.js
    - Input
      - index.js
      - Input.js
      - utils.js
      - focusManager.js
    - Card
      - index.js
      - Card.js
      - CardDivider.js
    - Button.js
    - Typography.js

```jsx
import React from 'react'
import Breadcrumb, {
  CollapsedSeparator,
  Expander,
  BreadcrumbText,
  BreadcrumbHotdog,
  BreadcrumbFishes,
  BreadcrumbLeftOvers,
  BreadcrumbHead,
  BreadcrumbAddict,
  BreadcrumbDragon0814,
} from '../../../../../../../../../../components/Breadcrumb'

const withBreadcrumbHotdog = (WrappedComponent) => (props) => (
  <WrappedComponent BreadcrumbHotdog={BreadcrumbHotdog} {...props} />
)

const WorldOfBreadcrumbs = ({
  BreadcrumbHotdog: BreadcrumbHotdogComponent,
}) => {
  const [hasFishes, setHasFishes] = React.useState(false)

  return (
    <BreadcrumbDragon0814
      hasFishes={hasFishes}
      render={(results) => (
        <BreadcrumbFishes>
          {({ breadcrumbFishes }) => (
            <BreadcrumbLeftOvers.Provider>
              <BreadcrumbHotdogComponent>
                <Expander>
                  <BreadcrumbText>
                    <BreadcrumbAddict>
                      <pre>
                        <code>{JSON.stringify(results, null, 2)}</code>
                      </pre>
                    </BreadcrumbAddict>
                  </BreadcrumbText>
                </Expander>
                {hasFishes
                  ? breadcrumbFishes.map((fish) => (
                      <>
                        {fish}
                        <CollapsedSeparator />
                      </>
                    ))
                  : null}
              </BreadcrumbHotdogComponent>
            </BreadcrumbLeftOvers.Provider>
          )}
        </BreadcrumbFishes>
      )}
    />
  )
}

export default withBreadcrumbHotdog(WorldOfBreadcrumbs)
```

## 3. Name Your Components Using Standard Naming Conventions

Naming your components using standard conventions makes it easier for other developers to read your code.

For example, [higher order components](https://reactjs.org/docs/higher-order-components.html) usually becomes prefixed with `with` which most people are used to:

```jsx
import React from 'react'
import hoistNonReactStatics from 'hoist-non-react-statics'
import getDisplayName from 'utils/getDisplayName'

const withFreeMoney = (WrappedComponent) => {
  class WithFreeMoney extends React.Component {
    giveFreeMoney() {
      return 50000
    }

    render() {
      return (
        <WrappedComponent
          additionalMoney={[
            this.giveFreeMoney(),
            this.giveFreeMoney(),
            this.giveFreeMoney(),
            this.giveFreeMoney(),
            this.giveFreeMoney(),
            this.giveFreeMoney(),
            this.giveFreeMoney(),
          ]}
          {...this.props}
        />
      )
    }
  }

  WithFreeMoney.displayName = `withFreeMoney(${getDisplayName(
    WrappedComponent,
  )}$)`
  hoistNonReactStatics(WithFreeMoney, WrappedComponent)

  return WithFreeMoney
}

export default withFreeMoney
```

If you decide to do something different like this:

```jsx
import React from 'react'
import hoistNonReactStatics from 'hoist-non-react-statics'
import getDisplayName from 'utils/getDisplayName'

const useFreeMoney = (WrappedComponent) => {
  class WithFreeMoney extends React.Component {
    giveFreeMoney() {
      return 50000
    }

    render() {
      return (
        <WrappedComponent
          additionalMoney={[
            this.giveFreeMoney(),
            this.giveFreeMoney(),
            this.giveFreeMoney(),
            this.giveFreeMoney(),
            this.giveFreeMoney(),
            this.giveFreeMoney(),
            this.giveFreeMoney(),
          ]}
          {...this.props}
        />
      )
    }
  }

  WithFreeMoney.displayName = `useFreeMoney(${getDisplayName(
    WrappedComponent,
  )}$)`
  hoistNonReactStatics(WithFreeMoney, WrappedComponent)

  return WithFreeMoney
}

export default useFreeMoney
```

It's perfectly valid JavaScript and there's _nothing wrong_ with naming it this way. But there's already a standard naming convention for `use` which have already reached the scene with [react hooks](https://reactjs.org/docs/hooks-reference.html). Just be careful when you're sharing your code especially when you're asking for help because people might already be adapted to seeing common established conventions every day.

## 4. Avoid the Boolean Trap

You have to be extra careful when deciding your output when it comes to the primitive booleans to determine output value of something. It's known to be a code smell and it forces the developer to look at the source code / implementation of the component to be able to make an accurate assumption of the end result.

For example, if we declared a Typography component that takes these available options: `'h1'`, `'h2'`, `'h3'`, `'h4'`, `'h5'`, `'h6'`, `'title'`, `'subheading'`

How would you figure out how they'll be applied when they're passed in like this?

```jsx
const App = () => (
  <Typography color="primary" align="center" subheading title>
    Welcome to my bio
  </Typography>
)
```

Those who are more experienced with React (or more appropriately, _JavaScript_) might already guess that `title` will proceed over `subheading` because by the way the ordering works, the last one will overwrite the previous.

But the problem is that we won't be able to truly tell how far `title` or `subheading` will be applied without looking at the source code.

For example:

```css
.title {
  font-size: 1.2rem;
  font-weight: 500;
  text-transform: uppercase;
}

.subheading {
  font-size: 1.1rem;
  font-weight: 400;
  text-transform: none !important;
}
```

Even though `title` "wins", the `text-transform: uppercase` CSS line _still won't be applied_ because `subheading` declares higher specificity with `text-transform: none !important;` in its implementation. If we aren't careful enough it might become really difficult to debug a styling issue _especially when it won't show any warnings/errors to the console_. This can complicate the component's signature.

Here's just one example of a cleaner alternative to re-implement the `Typography` component that solves the issue:

```jsx
const App = () => <Typography variant="title">Welcome to my bio</Typography>
```

**Typography**

```jsx
import React from 'react'
import cx from 'classnames'
import styles from './styles.css'

const Typography = ({
  children,
  color = '#333',
  align = 'left',
  variant,
  ...otherProps
}) => {
  return (
    <div
      className={cx({
        [styles.h1]: variant === 'h1',
        [styles.h2]: variant === 'h2',
        [styles.h3]: variant === 'h3',
        [styles.h4]: variant === 'h4',
        [styles.h5]: variant === 'h5',
        [styles.h6]: variant === 'h6',
        [styles.title]: variant === 'title',
        [styles.subheading]: variant === 'subheading',
      })}
    >
      {children}
    </div>
  )
}
```

Now when we pass `variant="title"` in the `App` component, we will be assured that only `title` will be applied and it saves us the trouble of having to look at the source code to determine the outcome.

You can also just do a simple if/else to compute the prop:

```jsx
let result
if (variant === 'h1') result = styles.h1
else if (variant === 'h2') result = styles.h2
else if (variant === 'h3') result = styles.h3
else if (variant === 'h4') result = styles.h4
else if (variant === 'h5') result = styles.h5
else if (variant === 'h6') result = styles.h6
else if (variant === 'title') result = styles.title
else if (variant === 'subheading') result = styles.subheading
```

But the best benefit from this is that you can just do this simple, clean one-liner and call it a day:

```jsx
const result = styles[variant]
```

## 5. Use Fat Arrow Functions

Using fat arrow functions is a shorter and concise way of declaring functions in JavaScript (which is more appropriately named a _function expression_ in this case).

However, there are certain times when you _don't_ want to use fat arrow functions over function expressions, like when you need the hoisting.

In React, the same concept applies similarly. However, if you _don't_ need hoisting it's a nicer alternative (in my opinion) to use the arrow syntax:

```jsx
// Function declaration version
function Gallery({ title, images = [], ...otherProps }) {
  return (
    <CarouselContext.Provider>
      <Carousel>
        {images.map((src, index) => (
          <img src={src} key={`img_${index}`} />
        ))}
      </Carousel>
    </CarouselContext.Provider>
  )
}

// Arrow / Function expression version
const Gallery = ({ title, images = [], ...otherProps }) => (
  <CarouselContext.Provider>
    <Carousel>
      {images.map((src, index) => (
        <img src={src} key={`img_${index}`} />
      ))}
    </Carousel>
  </CarouselContext.Provider>
)
```

But you can hardly tell the benefits in this example... The beauty of arrow functions shine when you do simple one-liners:

```jsx
// Function declaration version
function GalleryPage(props) {
  return <Gallery {...props} />
}

// Arrow / Function expression version
const GalleryPage = (props) => <Gallery {...props} />
```

And one-liners makes everyone happy! :)

## 6. Put Independent Functions Outside of Your Custom Hooks

I see some people declaring functions inside their custom hooks when they aren't really needed by them. This makes the custom hook a little bloated and harder to read as it gets longer because some developers might begin to question if the hook actually _does_ depend on the function being inside the hook. If it's not, its better to move it outside so that there's a clear understanding of what the dependencies of the hook are and which ones aren't.

Here's an example:

```jsx
import React from 'react'

const initialState = {
  initiated: false,
  images: [],
}

const reducer = (state, action) => {
  switch (action.type) {
    case 'initiated':
      return { ...state, initiated: true }
    case 'set-images':
      return { ...state, images: action.images }
    default:
      return state
  }
}

const usePhotosList = ({ imagesList = [] }) => {
  const [state, dispatch] = React.useReducer(reducer, initialState)

  const removeFalseyImages = (images = []) =>
    images.reduce((acc, img) => (img ? [...acc, img] : acc), [])

  React.useEffect(() => {
    const images = removeFalseyImages(imagesList)
    dispatch({ type: 'initiated' })
    dispatch({ type: 'set-images', images })
  }, [])

  return {
    ...state,
  }
}

export default usePhotosList
```

Looking at the example, `removeFalseyImages` actually doesn't need to be inside the custom hook and can instead be extracted _outside_ and still be used without any problems inside of the hook since it doesn't interact with any of its state.

## 7. Stay Consistent

Staying consistent is also a commonly recommended approach in JavaScript.

As for React, stay consistent with:

1. Imports and exports
2. Naming components, hooks, HOC's, classNames

When importing and exporting components, I sometimes like using this syntax when I want to put exports in between:

```jsx
import App from './App'

export { default as Breadcrumb } from './Breadcrumb'

export default App
```

But I equally love this syntax:

```jsx
export { default } from './App'
export { default as Breadcrumb } from './Breadcrumb'
```

Whichever one you like doing, just make sure that you're consistent with choosing one for each project so that it stays simple.

Staying consistent with naming conventions is also a very important rule.

When you define a hook like `useApp`, it's important to name your next hook with the prefix `use` like `useController`.

If you don't, what you end up doing is something like this:

```jsx
// custom hook #1
const useApp = ({ data: dataProp = null }) => {
  const [data, setData] = React.useState(dataProp)

  React.useEffect(() => {
    setData(data)
  }, [])

  return {
    data,
  }
}

// custom hook #2
const basicController = ({ device: deviceProp }) => {
  const [device, setDevice] = React.useState(deviceProp)

  React.useEffect(() => {
    if (!device && deviceProp) {
      setDevice(deviceProp === 'mobile' ? 'mobile' : 'desktop')
    }
  }, [deviceProp])

  return {
    device,
  }
}
```

Importing the two hooks:

```jsx
import React from 'react'
import useApp from './useApp'
import basicController from './basicController'

const App = () => {
  const app = useApp()
  const controller = basicController()

  return (
    <div>
      {controller.errors.map((errorMsg) => (
        <div>{errorMsg}</div>
      ))}
    </div>
  )
}

export default App
```

It's not immediately obvious that `basicController` is a custom react hook just like `useApp` is and forces the developer to look and read inside the code to really figure out the truth. If we kept it consistent, it wouldn't have turned out that way because we can make it obvious:

```jsx
const app = useApp()
const controller = useBasicController()
```

## 8. Componentize Duplicate Elements

_Componentize_ is just a fancy way of saying "converting duplicate elements to their own reusable component".

Everybody has their reasons for writing duplicate code in React whether it was intentional or an accident.

What ever the cause, it's a good idea for you to not leave plenty of duplicode code untouched.

For one, you're probably forming a habit of likely doing that again because you didn't care about the previous duplicated code. How are you a team player by doing this? You're putting a burden on your teammates in the future because they're probably going to get frustrated seeing duplicate elements and they might even be confused especially when they're put to the task of editing them.

The worst part is for them to get criticized by their duplicate code when they didn't even write it. When they do, just took one for the team on your behalf. Repay them back by avoiding the duplication in the future!

Lets take a look at this code below and componentize the duplicate parts:

```jsx
const SomeComponent = () => (
  <Body noBottom>
    <Header center>Title</Header>
    <Divider />
    <Background grey>
      <Section height={500}>
        <Grid spacing={16} container>
          <Grid xs={12} sm={6} item>
            <div className={classes.groupsHeader}>
              <Header center>Groups</Header>
            </div>
          </Grid>
          <Grid xs={12} sm={6} item>
            <div>
              <img src={photos.groups} alt="" className={classes.img} />
            </div>
          </Grid>
        </Grid>
      </Section>
    </Background>
    <div>
      <Section height={500}>
        <Grid spacing={16} container>
          <Grid xs={12} sm={6} item>
            <div className={classes.labsHeader}>
              <Header center>Labs</Header>
            </div>
          </Grid>
          <Grid xs={12} sm={6} item>
            <div>
              <img src={photos.labs} alt="" className={classes.img} />
            </div>
          </Grid>
        </Grid>
      </Section>
    </div>
  </Body>
)
```

Now if someone were to tell you to change the grid sizes from `xs={12} sm={6}` to `xs={12} sm={4}` it would become a hassle because you have to change that four times.

The beauty of compenentizing is that you can just make a single change and it will reflect throughout all of the grids:

```jsx
const SomeComponent = ({ classes, xs = 12, sm = 6, md, lg }) => {
  const BodySection = ({ header, src }) => {
    const gridSizes = { xs, sm, md, lg }
    return (
      <Section height={500}>
        <Grid spacing={16} container>
          <Grid {...gridSizes} item>
            <div className={classes.groupsHeader}>
              <Header center>{header}</Header>
            </div>
          </Grid>
          <Grid {...gridSizes} item>
            <div>
              <img src={src} alt="" className={classes.img} />
            </div>
          </Grid>
        </Grid>
      </Section>
    )
  }

  return (
    <Body noBottom>
      <Header center>Title</Header>
      <Divider />
      <Background grey>
        <BodySection header="Groups" src={photos.groups} />
      </Background>
      <div>
        <BodySection header="Labs" src={photos.labs} />
      </div>
    </Body>
  )
}
```

At its most basic level of extraction, this became much easier for humans to read and maintain while still keeping the normal implementation in place!

## 9. Keep Your Components Simple

Something I've learned while working for a production web app wasn't to keep your components simple, but to _avoid_ making your components complicated.

Here's an example of a component that was unnecessarily complicated:

_ConfirmAvailability.js_

```jsx
import React from 'react'
import Grid from '@material-ui/core/Grid'
import Typography from '@material-ui/core/Typography'
import MenuItem from '@material-ui/core/MenuItem'
import Select from '@material-ui/core/Select'
import Time from 'util/time'

/**
 * Timezone picker. Automatically detects the timezone from the client's device but also displays
 * a clock using this timezone to make sure it is correct. If not, the user may override it.
 *
 * NOTE: Be careful about Date().getTimezoneOffset(). It does two things differently from standard
 *      1. Time difference is in minutes
 *      2. Time difference is from local to UTC, not UTC to local. This means it will be negative of
 *          the expected UTC format
 */
export default class TimeZonePicker extends React.Component {
  state = {
    time: new Date(),
    offset: -(new Date().getTimezoneOffset() / 60),
  }

  componentDidMount() {
    this.props.setOffset(this.state.offset)
  }

  handleChange = (event) => {
    const d = new Date()
    d.setTime(
      d.getTime() +
        d.getTimezoneOffset() * 60 * 1000 +
        event.target.value * 3600 * 1000,
    )
    this.setState({
      time: d,
      offset: event.target.value,
    })
    this.props.setOffset(event.target.value)
  }

  render() {
    const timezones = []
    for (let i = -12; i <= 14; i++) {
      timezones.push(
        <MenuItem key={i} value={i}>
          {i > 0 ? '+' : null}
          {i}
        </MenuItem>,
      )
    }

    return (
      <React.Fragment>
        <Grid container justify="space-between">
          <div>
            <Typography>Current time</Typography>
            <Typography variant="h6" gutterBottom>
              {Time.formatTime(this.state.time)}
            </Typography>
          </div>
          <div>
            <Typography>Set timezone</Typography>
            <Select value={this.state.offset} onChange={this.handleChange}>
              {timezones}
            </Select>
          </div>
        </Grid>
      </React.Fragment>
    )
  }
}
```

The component was intended to be a simple component but since the logic was tightly coupled it was _responsible for multiple things_. At the time this code was written, react hooks was not yet released, but there were still higher order components and render props. So we'll just use one of those patterns to rewrite this to be simpler just to demonstrate how to keep your components simpler (without changing the functionality):

`SelectTimeZone.js`

```jsx
import React from 'react'

/**
 * Timezone picker. Automatically detects the timezone from the client's device but also displays
 * a clock using this timezone to make sure it is correct. If not, the user may override it.
 *
 * NOTE: Be careful about Date().getTimezoneOffset(). It does two things differently from standard
 *      1. Time difference is in minutes
 *      2. Time difference is from local to UTC, not UTC to local. This means it will be negative of
 *          the expected UTC format
 */

class SelectTimeZone extends React.Component {
  state = {
    time: new Date(),
    offset: -(new Date().getTimezoneOffset() / 60),
  }

  componentDidMount() {
    this.props.setOffset(this.state.offset)
  }

  handleChange = (event) => {
    const d = new Date()
    d.setTime(
      d.getTime() +
        d.getTimezoneOffset() * 60 * 1000 +
        event.target.value * 3600 * 1000,
    )
    this.setState({
      time: d,
      offset: event.target.value,
    })
    this.props.setOffset(event.target.value)
  }

  getTimeZones = () => {
    const timezones = []
    for (let i = -12; i <= 14; i++) {
      timezones.push(
        <MenuItem key={i} value={i}>
          {i > 0 ? '+' : null}
          {i}
        </MenuItem>,
      )
    }
    return timezones
  }

  render() {
    return this.props.render({
      ...this.state,
      getTimeZones: this.getTimeZones,
    })
  }
}
```

`TimeZonePicker.js`

```jsx
import React from 'react'
import Grid from '@material-ui/core/Grid'
import Typography from '@material-ui/core/Typography'
import MenuItem from '@material-ui/core/MenuItem'
import Select from '@material-ui/core/Select'
import Time from 'util/time'

const TimeZonePicker = () => (
  <SelectTimeZone
    render={({ time, offset, getTimeZones, handleChange }) => (
      <Grid container justify="space-between">
        <div>
          <Typography>Current time</Typography>
          <Typography variant="h6" gutterBottom>
            {Time.formatTime(time)}
          </Typography>
        </div>
        <div>
          <Typography>Set timezone</Typography>
          <Select value={offset} onChange={handleChange}>
            {getTimeZones()}
          </Select>
        </div>
      </Grid>
    )}
  />
)

export default TimeZonePicker
```

Now we have a much cleaner approach and extracted out the logic from its presentational counterpart. Unit testing these components now becomes _much_ easier!

## 10. Use `useReducer` if `useState` becomes complex

When you're having multiple states to keep track of, using `useState` begins to become harder to manage.

This can look something like this:

```jsx
import React from 'react'
import axios from 'axios'

const useFrogs = () => {
  const [fetching, setFetching] = React.useState(false)
  const [fetched, setFetched] = React.useState(false)
  const [fetchError, setFetchError] = React.useState(null)
  const [timedOut, setTimedOut] = React.useState(false)
  const [frogs, setFrogs] = React.useState(null)
  const [params, setParams] = React.useState({ limit: 50 })
  const timedOutRef = React.useRef()

  function updateParams(newParams) {
    if (newParams != undefined) {
      setParams(newParams)
    } else {
      console.warn(
        'You tried to update state.params but the parameters were null or undefined',
      )
    }
  }

  function formatFrogs(newFrogs) {
    const formattedFrogs = newFrogs.reduce((acc, frog) => {
      const { name, age, size, children } = frog
      if (!(name in acc)) {
        acc[name] = {
          age,
          size,
          children: children.map((child) => ({
            name: child.name,
            age: child.age,
            size: child.size,
          })),
        }
      }
      return acc
    }, {})
    return formattedFrogs
  }

  function addFrog(name, frog) {
    const nextFrogs = {
      ...frogs,
      [name]: frog,
    }
    setFrogs(nextFrogs)
  }

  function removeFrog(name) {
    const nextFrogs = { ...frogs }
    if (name in nextFrogs) delete nextFrogs[name]
    setFrogs(nextFrogs)
  }

  React.useEffect(() => {
    if (frogs === null) {
      if (timedOutRef.current) clearTimeout(timedOutRef.current)

      setFetching(true)

      timedOutRef.current = setTimeout(() => {
        setTimedOut(true)
      }, 20000)

      axios
        .get('https://somefrogsaspi.com/api/v1/frogs_list/', { params })
        .then((response) => {
          if (timedOutRef.current) clearTimeout(timedOutRef.current)
          setFetching(false)
          setFetched(true)
          if (timedOut) setTimedOut(false)
          if (fetchError) setFetchError(null)
          setFrogs(formatFrogs(response.data))
        })
        .catch((error) => {
          if (timedOutRef.current) clearTimeout(timedOutRef.current)
          console.error(error)
          setFetching(false)
          if (timedOut) setTimedOut(false)
          setFetchError(error)
        })
    }
  }, [])

  return {
    fetching,
    fetched,
    fetchError,
    timedOut,
    frogs,
    params,
    addFrog,
    removeFrog,
  }
}

export default useFrogs
```

This would become more manageable if you were to convert this to a `useReducer`:

```jsx
import React from 'react'
import axios from 'axios'

const initialFetchState = {
  fetching: false
  fetched: false
  fetchError: null
  timedOut: false
}

const initialState = {
  ...initialFetchState,
  frogs: null
  params: { limit: 50 }
}

const reducer = (state, action) => {
  switch (action.type) {
    case 'fetching':
      return { ...state, ...initialFetchState, fetching: true }
    case 'fetched':
      return { ...state, ...initialFetchState, fetched: true, frogs: action.frogs }
    case 'fetch-error':
      return { ...state, ...initialFetchState, fetchError: action.error }
    case 'set-timed-out':
      return { ...state, ...initialFetchState, timedOut: true }
    case 'set-frogs':
      return { ...state, ...initialFetchState, fetched: true, frogs: action.frogs }
    case 'add-frog':
      return { ...state, frogs: { ...state.frogs, [action.name]: action.frog }}
    case 'remove-frog': {
      const nextFrogs = { ...state.frogs }
      if (action.name in nextFrogs) delete nextFrogs[action.name]
      return { ...state, frogs: nextFrogs }
    }
    case 'set-params':
      return { ...state, params: { ...state.params, ...action.params } }
      default:
        return state
  }
}

const useFrogs = () => {
  const [state, dispatch] = React.useReducer(reducer, initialState)
  const timedOutRef = React.useRef()

  function updateParams(params) {
    if (newParams != undefined) {
      dispatch({ type: 'set-params', params })
    } else {
      console.warn(
        'You tried to update state.params but the parameters were null or undefined',
      )
    }
  }

  function formatFrogs(newFrogs) {
    const formattedFrogs = newFrogs.reduce((acc, frog) => {
      const { name, age, size, children } = frog
      if (!(name in acc)) {
        acc[name] = {
          age,
          size,
          children: children.map((child) => ({
            name: child.name,
            age: child.age,
            size: child.size,
          })),
        }
      }
      return acc
    }, {})
    return formattedFrogs
  }

  function addFrog(name, frog) {
    dispatch({ type: 'add-frog', name, frog })
  }

  function removeFrog(name) {
    dispatch({ type: 'remove-frog', name })
  }

  React.useEffect(() => {
    if (frogs === null) {
      if (timedOutRef.current) clearTimeout(timedOutRef.current)

      timedOutRef.current = setTimeout(() => {
        setTimedOut(true)
      }, 20000)

      axios
        .get('https://somefrogsaspi.com/api/v1/frogs_list/', { params })
        .then((response) => {
          if (timedOutRef.current) clearTimeout(timedOutRef.current)
          const frogs = formatFrogs(response.data)
          dispatch({ type: 'set-frogs', frogs })
        })
        .catch((error) => {
          if (timedOutRef.current) clearTimeout(timedOutRef.current)
          console.error(error)
          dispatch({ type: 'fetch-error', error })
        })
    }
  }, [])

  return {
    fetching,
    fetched,
    fetchError,
    timedOut,
    frogs,
    params,
    addFrog,
    removeFrog,
  }
}

export default useFrogs
```

Although this may arguably not be cleaner than the `useState` approach when you look at it, it _is_ easier to manage when you're implementing the custom hook using the `useReducer` version because you don't have to worry about keeping track of state updates in multiple parts of the hook since you'll have it all defined in one place inside the `reducer`.

We've also now defined an "official" set of rules of how the manipulation of state.frogs will be manipulated inside the `reducer` function and have a direct, clearer separation of logic. In other words, if we were to continue using `useState` for this there won't be a pre-defined entity unlike the `useReducer` where all the logic was placed inside the `reducer`.

In the `useState` version, we had to declare functions inside the hook in order to figure out the next part of the state, in addition to writing the logic, where as in the `useReducer` version we didn't have to do that and instead moved them to the `reducer` function. We just needed to _call_ the type of action and that's all it needed to worry about :)

## 11. Use Function Declaration In Dull Areas

A good example of this is the `useEffect` clean up handler:

```jsx
React.useEffect(() => {
  setMounted(true)

  return () => {
    setMounted(false)
  }
}, [])
```

As react developers who know what this does it's not a problem. But if you assume that other people are going to be reading your code it's a good idea to be explicit with code like this using function declarations because we get to name them to our advantage. For example:

```jsx
React.useEffect(() => {
  setMounted(true)

  return function cleanup() {
    setMounted(false)
  }
}, [])
```

This more clearly describes what happens when you return the function.

## 12. Use Prettier

[Prettier](https://prettier.io/) helps you and your team stay consistent with code formatting. It saves time, energy, and reduces the need to discuss the style in code reviews. It also enforces clean code practices which you can configure based on your opinions on what feels right and what doesn't.

## 13. Use Small Fragment over Large Fragment

_Small fragment_

```jsx
const App = () => (
  <>
    <FrogsTable />
    <FrogsGallery />
  </>
)
```

_Large Fragment_

```jsx
const App = () => (
  <React.Fragment>
    <FrogsTable />
    <FrogsGallery />
  </React.Fragment>
)
```

## 14. Put Things in Order

Something I like to do when writing code is to put things in order, like when importing files (except the `react` import):

```js
import React from 'react'
import { useSelector } from 'react-redux'
import styled from 'styled-components'
import FrogsGallery from './FrogsGallery'
import FrogsTable from './FrogsTable'
import Stations from './Stations'
import * as errorHelpers from '../utils/errorHelpers'
import * as utils from '../utils/'
```

Some of you may think to yourself that this isn't even in alphabetical order. That's only part of what this ordering scheme is.

The way I like to order my imports for a clean approach is using these guidelines, in order of precedence:

1. React import
2. Library imports (Alphabetical order)
3. Absolute imports from project (Alphabetical order)
4. Relative imports (Alphabetical order)
5. `import * as`
6. `import './<some file>.<some ext>'`

And I also like to order variables in other ways:

```js
const character = (function() {
  return {
    cry() {
      //
    },
    eat() {
      //
    },
    hop() {
      //
    },
    jump() {
      //
    },
    punch() {
      //
    },
    run() {
      //
    },
    scratch() {
      //
    },
    scream() {
      //
    },
    sleep() {
      //
    },
    walk() {
      //
    },
    yawn() {
      //
    },
  }
})()
```

Following a guideline helps for a cleaner code base.

## Conclusion

And that concludes the end of this post! I hope you found this to be useful and stay tuned for more!

Find me on [medium](https://medium.com/@jsmanifest)