8 Useful Practices for React Apps You Should Know
Tags: javascript, react, node
Published: 2019-11-13 03:52:06

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

React has gone through many shifts in stages that never fail to amaze its fans.

At first, we had [mixins](https://www.reddit.com/r/reactjs/comments/alc005/what_exactly_is_a_mixin/) to create and manage our interface, then came the concept of [class components](https://reactjs.org/docs/react-component.html), and now [react hooks](https://reactjs.org/docs/hooks-intro.html) which has changed the way we build our apps in react.

You know what else is great? Knowing some neat tricks you can do in react that will help you to build your apps better (if you came across something you didn't know you can do of course).

This article will go over 8 neat tricks in react that every react developer should know. Now i'm not expecting every single item in this list to be new to you, but i'm hoping that you find at least one item in this list useful to you that you didn't know you could do until now.

Here are 8 tricks in react you should know:

## 1. Create react elements with strings

The first item on this list will go over creating a regular react DOM element with simple strings that represent an HTML DOM element tag. More precisely, a string that represents a DOM element.

For example, you can create react components by assigning the string `'div'` to a variable like so:

```jsx
import React from 'react'

const MyComponent = 'div'

function App() {
  return (
    <div>
      <h1>Hello</h1>
      <hr />
      <MyComponent>
        <h3>I am inside a {'<div />'} element</h3>
      </MyComponent>
    </div>
  )
}
```

React will just call `React.createElement` and use that string to create the element internally. Isn't that neat?

Used commonly in component libraries like [Material-UI](material-ui.com), you can declare a `component` prop which the caller can decide the root node of the component to become the value of `props.component` like so:

```jsx
function MyComponent({ component: Component = 'div', name, age, email }) {
  return (
    <Component>
      <h1>Hi {name}</h1>
      <div>
        <h6>You are {age} years old</h6>
        <small>Your email is {email}</small>
      </div>
    </Component>
  )
}
```

This is how you can use it:

```jsx
function App() {
  return (
    <div>
      <MyComponent component="div" name="George" age={16} email="george@gmail.com">
    </div>
  )
}
```

You can also pass in your custom component where that will be used as the root node:

```jsx
function Dashboard({ children }) {
  return (
    <div style={{ padding: '25px 12px' }}>
      {children}
    </div>
  )
}

function App() {
  return (
    <div>
      <MyComponent component={Dashboard} name="George" age={16} email="george@gmail.com">
    </div>
  )
}
```

## 2. Use Error Boundaries

In JavaScript, we are used to handling _most_ errors inside the execution of code with `try/catch`--the block of code that can _"catch"_ errors that occur. When these errors are caught in the catch block, you can save your application from crashing within code boundaries.

An example of this would look something like this:

```js
function getFromLocalStorage(key, value) {
  try {
    const data = window.localStorage.get(key)
    return JSON.parse(data)
  } catch (error) {
    console.error
  }
}
```

React is ultimately just JavaScript so we may assume that we can catch and handle errors using the same strategy. However, due to the nature of react, JavaScript errors inside components corrupt react's internal state and cause it to [emit cryptic](https://github.com/facebook/react/issues/4026) [errors](https://github.com/facebook/react/issues/8579) on future renders.

For this reason the react team introduced [error boundaries](https://reactjs.org/docs/error-boundaries.html), and every react developer should know about them so they can use them in their react apps.

The problem with errors happening prior to error boundaries was that when these cryptic errors were emitted in future renders after happening in previous renders, react did not provide a way to handle nor recover from them in components. This is why we all need error boundaries!

Error boundaries are react components that catch errors anywhere in the component tree, log them, and can display a fallback UI instead of the component tree that crashed. They catch errors during rendering, inside lifecycle methods, and inside the constructors of the entire tree below them (which is the reason why we declare and render them at the top of our app somewhere).

Here is an example from the [react documentation](https://reactjs.org/docs/error-boundaries.html#introducing-error-boundaries):

```js
class ErrorBoundary extends React.Component {
  constructor(props) {
    super(props)
    this.state = { hasError: false }
  }

  static getDerivedStateFromError(error) {
    // Update state so the next render will show the fallback UI.
    return { hasError: true }
  }

  componentDidCatch(error, errorInfo) {
    // You can also log the error to an error reporting service
    logErrorToMyService(error, errorInfo)
  }

  render() {
    if (this.state.hasError) {
      // You can render any custom fallback UI
      return <h1>Something went wrong.</h1>
    }

    return this.props.children
  }
}
```

Then you can use it as a regular component:

```js
<ErrorBoundary>
  <MyWidget />
</ErrorBoundary>
```

## 3. Retain Previous Values

While updating props or state, you can retain their previous values just by using `React.useRef`

For example, to track the current and previous changes of an array of items, you would can create a `React.useRef` which gets assigned the previous value and a `React.useState` for the current value:

```js
function MyComponent() {
  const [names, setNames] = React.useState(['bob'])
  const prevNamesRef = React.useRef([])

  React.useEffect(() => {
    prevNamesRef.current = names
  })

  const prevNames = prevNamesRef.current

  return (
    <div>
      <h4>Current names:</h4>
      <ul>
        {names.map((name) => (
          <li key={name}>{name}</li>
        ))}
      </ul>
      <h4>Previous names:</h4>
      <ul>
        {prevNames.map((prevName) => (
          <li key={prevName}>{prevName}</li>
        ))}
      </ul>
    </div>
  )
}
```

This works because `React.useEffect` is run _after the components finished rendering_.

When `setNames` is called, the component re-renders and `prefNamesRef` will hold the previous names because `React.useEffect` is the last code executed from the _previous render_. And since we re-assigned `prevNamesRef.current` in the `useEffect`, it becomes the previous names in the next render phase because it was last assigned the names from the previous render phase.

## 4. Use `React.useRef` for flexible non-stale value checks

Before react hooks were introduced in react, we had the `componentDidMount` static method of class components if we wanted to ensure operations like fetching data happened _after_ the component mounted on the DOM.

When react hooks came out it quickly became the most popular way to write our components as opposed to using class components. When we wanted to track if a component has mounted to prevent setting the state after the component unmounts we would do something like so:

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

class MyComponent extends React.Component {
  mounted = false

  state = {
    frogs: [],
    error: null,
  }

  componentDidMount() {
    this.mounted = true
  }

  componentWillUnmount() {
    this.mounted = false
  }

  async fetchFrogs = (params) => {
    try {
      const response = await axios.get('https://some-frogs-api.com/v1/', { params })
      if (this.mounted) {
        this.setState({ frogs: response.data.items })
      }
    } catch (error) {
      if (this.mounted) {
        this.setState({ error })
      }
    }
  }

  render() {
    return (
      <div>
        <h4>Frogs:</h4>
        <ul>
        {this.state.frogs.map((frog) => <li key={frog.name}>{frog.name}</li>
        )}
        </ul>
    </div>
    )
  }
}
```

Hooks did not have a `componentDidMount` after migrating to react hooks and the concept of memory leaks from state updates occurring after unmounting still applies with hooks.

However, a similar way to `componentDidMount` using react hooks is to use `React.useEffect` since it is executed _after_ components are finished rendering. If you use `React.useRef` to assign the value of the mounted value here you can achieve the same effect as the class component example:

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

function MyComponent() {
  const [frogs, setFrogs] = React.useState([])
  const [error, setError] = React.useState(null)
  const mounted = React.useRef(false)

  async function fetchFrogs(params) {
    try {
      const response = await axios.get('https://some-frogs-api.com/v1/', {
        params,
      })
      if (mounted.current) {
        setFrogs(response.data.items)
      }
    } catch (error) {
      if (mounted.current) {
        setError(error)
      }
    }
  }

  React.useEffect(() => {
    mounted.current = true

    return function cleanup() {
      mounted.current = false
    }
  }, [])

  return (
    <div>
      <h4>Frogs:</h4>
      <ul>
        {this.state.frogs.map((frog) => (
          <li key={frog.name}>{frog.name}</li>
        ))}
      </ul>
    </div>
  )
}
```

Another example of a good use case to keep track of latest changes without causing re-renders is to use it in conjunction with `React.useMemo` like this ([source](https://github.com/mui-org/material-ui/blob/master/packages/material-ui/src/utils/useForkRef.js)):

```jsx
function setRef(ref, value) {
  // Using function callback version
  if (typeof ref === 'function') {
    ref(value)
    // Using the React.useRef() version
  } else if (ref) {
    ref.current = value
  }
}

function useForkRef(refA, refB) {
  return React.useMemo(() => {
    if (refA == null && refB == null) {
      return null
    }
    return (refValue) => {
      setRef(refA, refValue)
      setRef(refB, refValue)
    }
  }, [refA, refB])
}
```

This will create a new function if the ref props change and are defined. This means that react will call the old forked ref with `null`, and the new forked ref with the current ref. And since `React.useMemo` is used, the refs will be memoized until ref props of `refA` or `refB` change--in which natural cleanup occurs from this behavior.

## 5. Use `React.useRef` for customizing elements that depend on other elements

`React.useRef` has several useful use cases including assigning itself to the ref prop to react nodes:

```jsx
function MyComponent() {
  const [position, setPosition] = React.useState({ x: 0, y: 0 })
  const nodeRef = React.useRef()

  React.useEffect(() => {
    const pos = nodeRef.current.getBoundingClientRect()
    setPosition({
      x: pos.x,
      y: pos.y,
    })
  }, [])

  return (
    <div ref={nodeRef}>
      <h2>Hello</h2>
    </div>
  )
}
```

If we wanted to grab the position of the `div` element's coordinates, this example is sufficient. However, if another element somewhere in the app wants to update their own positions the same time `position` changes or apply some condition logic accordingly, the best way to do it is using the `ref callback function pattern`. When using the callback function pattern you will receive either the react component instance or HTML DOM element as the first argument.

The example below just shows a simple example where `setRef` is the callback function being applied to a `ref` prop. You can see that inside `setRef` you have the ability to do whatever you need as opposed to directly applying the `React.useRef` version to the DOM element:

```jsx
const SomeComponent = function({ nodeRef }) {
  const ownRef = React.useRef()

  function setRef(e) {
    if (e && nodeRef.current) {
      const codeElementBounds = nodeRef.current.getBoundingClientRect()
      // Log the <pre> element's position + size
      console.log(`Code element's bounds: ${JSON.stringify(codeElementBounds)}`)
      ownRef.current = e
    }
  }

  return (
    <div
      ref={setRef}
      style={{ width: '100%', height: 100, background: 'green' }}
    />
  )
}

function App() {
  const [items, setItems] = React.useState([])
  const nodeRef = React.useRef()

  const addItems = React.useCallback(() => {
    const itemNum = items.length
    setItems((prevItems) => [
      ...prevItems,
      {
        [`item${itemNum}`]: `I am item # ${itemNum}'`,
      },
    ])
  }, [items, setItems])

  return (
    <div style={{ border: '1px solid teal', width: 500, margin: 'auto' }}>
      <button type="button" onClick={addItems}>
        Add Item
      </button>
      <SomeComponent nodeRef={nodeRef} />
      <div ref={nodeRef}>
        <pre>
          <code>{JSON.stringify(items, null, 2)}</code>
        </pre>
      </div>
    </div>
  )
}
```

## 6. Higher Order Components

A common pattern in plain JavaScript to create powerful reusable functions is the [higher order function](https://eloquentjavascript.net/05_higher_order.html). Since react is ultimately JavaScript, you can also use higher order functions inside react.

For reusable _components_, the trick is to use _higher order components_.

A _higher order component_ is when you have a function that takes a component as an argument and returns a component. Just as how higher order functions can be employed to abstract away logic and be shared amongst other functions in the app, higher order components enable us to abstract away logic from components and share them amongst other components. This means that you can employ a bunch of reusable components to reuse across your application.

Here is an example of a higher order component. In this snippet, a higher order component `withBorder` takes in a custom component and returns a hidden _"middle layer"_ component. Then, when the parent decides to render this higher order component that was returned, it is called as a component and receives the props that was passed in from the "middle layer component":

```jsx
import React from 'react'

// Higher order component
const withBorder = (Component, customStyle) => {
  class WithBorder extends React.Component {
    render() {
      const style = {
        border: this.props.customStyle
          ? this.props.customStyle.border
          : '3px solid teal',
      }
      return <Component style={style} {...this.props} />
    }
  }

  return WithBorder
}

function MyComponent({ style, ...rest }) {
  return (
    <div style={style} {...rest}>
      <h2>This is my component and I am expecting some styles.</h2>
    </div>
  )
}

export default withBorder(MyComponent, {
  border: '4px solid teal',
})
```

## 7. Render Props

One of my favorite tricks to use in the react library is the _render prop pattern_. It is similar to higher order components in a way that it solves a similar problem: Sharing code between multiple components. Render props expose a function who's purpose is to pass back everything the outside world needs to render its children.

The most basic way to render components in react is to render them like so:

```jsx
function MyComponent() {
  return <p>My component</p>
}

function App() {
  const [fetching, setFetching] = React.useState(false)
  const [fetched, setFetched] = React.useState(false)
  const [fetchError, setFetchError] = React.useState(null)
  const [frogs, setFrogs] = React.useState([])

  React.useEffect(() => {
    setFetching(true)
    api
      .fetchFrogs({ limit: 1000 })
      .then((result) => {
        setFrogs(result.data.items)
        setFetched(true)
        setFetching(false)
      })
      .catch((error) => {
        setError(error)
        setFetching(false)
      })
  }, [])

  return (
    <MyComponent
      fetching={fetching}
      fetched={fetched}
      fetchError={fetchError}
      frogs={frogs}
    />
  )
}
```

With render props, the prop that renders its children is by convention called `render` like so:

```jsx
function MyComponent({ render }) {
  const [fetching, setFetching] = React.useState(false)
  const [fetched, setFetched] = React.useState(false)
  const [fetchError, setFetchError] = React.useState(null)
  const [frogs, setFrogs] = React.useState([])

  React.useEffect(() => {
    setFetching(true)
    api
      .fetchFrogs({ limit: 1000 })
      .then((result) => {
        setFrogs(result.data.items)
        setFetched(true)
        setFetching(false)
      })
      .catch((error) => {
        setError(error)
        setFetching(false)
      })
  }, [])

  return render({
    fetching,
    fetched,
    fetchError,
    frogs,
  })
}
```

In the example, `MyComponent` is an example of a component we refer to as the _render prop component_, because it expects `render` as a prop and calls it to render its children. This is a powerful pattern in react as we're allowed to pass in shared state and data through the render callback as arguments, allowing the component to be rendered and reused in multiple components:

```jsx
function App() {
  return (
    <MyComponent
      render={({ fetching, fetched, fetchError, frogs }) => (
        <div>
          {fetching
            ? 'Fetching frogs...'
            : fetched
            ? 'The frogs have been fetched!'
            : fetchError
            ? `An error occurred while fetching the list of frogs: ${fetchError.message}`
            : null}
          <hr />
          <ul
            style={{
              padding: 12,
            }}
          >
            {frogs.map((frog) => (
              <li key={frog.name}>
                <div>Frog's name: {frog.name}</div>
                <div>Frog's age: {frog.age}</div>
                <div>Frog's gender: {frog.gender}</div>
              </li>
            ))}
          </ul>
        </div>
      )}
    />
  )
}
```

## 8. Memoize

One of the most important things to know as a react developer is optimizing performance from your components like `React.memo`. This can help prevent nasty errors like _infinite loops_ that cause a catastrophic crash while the app is running.

Read about some of the several ways you can apply memoization in your react app below:

- [React.memo](https://reactjs.org/docs/react-api.html#reactmemo)
- [React.useMemo](https://flaviocopes.com/react-hook-usememo/)
- [React.useCallback](https://reactjs.org/docs/hooks-reference.html#usecallback)
- [React.PureComponent](https://reactjs.org/docs/react-api.html#reactpurecomponent)
- [Optimizing performance](https://reactjs.org/docs/optimizing-performance.html)

## Conclusion

And that concludes the end of this post! I hope you found this to be valuable and look out for more in the future!

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