Tips & Tricks that will make you a better React Developer
Tags: react, javascript, webdev, nextjs
Published: 2022-02-20 20:21:54

Coding, as a profession, requires constant and continuous learning, problem-solving, and staying up-to-date on the various helpful tools that are available out there. Developers need to always be on the lookout for easy wins. I appreciate developers who share their knowledge and I want to share some tricks that help me in React projects development. 

React only takes care of the view layer of an application, it doesn’t enforce any specific architecture (such as MVC or MVVM). This can make it difficult to keep your codebase organized as your React project grows. So, here are useful and time-saving tricks that you can use while developing.

> Good architecture makes the system easy to understand, easy to develop, easy to maintain, and easy to deploy. The ultimate goal is to minimize the lifetime cost of the system and to maximize programmer productivity. - _Robert C. Martin_

## Component Imports

Using absolute imports, you can alias folders like below:

```javascript
import { MyComponent } from 'components/MyComponent';
import useFetchData from 'hooks/useFetchData';
```
To set up absolute imports in your application add/update your `tsconfig.json` file if you use Typescript and `jsconfig.json` if you use JavaScript, in the root directory of the project. Then you need to update the compiler option `baseUrl` in the file.

```javascript
{
  "compilerOptions": {
    "baseUrl": "./src"
  },
  "include": ["src"]
}
```

## Custom Hooks

If you want to become a better React programmer, the best thing you can do is take the time to fully understand hooks.

Need to perform side effects? `useEffect` is for your friend. Examples of side effects are : data fetching, setting up a subscription, and manually changing the DOM React components.
Need to keep track of state between renders, and rerender when that state changes? `useState` has your back. Need to store and update a value between renders, without rendering? Or need to look up the height or width of a DOM element? `useRef` is your friend.

Keeping state business logic separate from UI. Rather than writing the logic for placement of the state inside a component, better to follow the Don't Repeat Yourself (DRY) principles, write code once and extract it into a hook of its own and related logic can be tightly coupled in a custom hook. 

Let's create a custom useFetch hook for API calls.

```javascript
import { useEffect, useState } from "react";

const useFetch = (url, method='GET', body={}) => {
  const [isLoading, setIsLoading] = useState(false);
  const [data, setData] = useState([]);
  const [isError, setIsError] = useState(false);

  useEffect(() => {
    if (!url) {
      return;
    }

    let isMounted = true;
    setIsLoading(true);

    const fetchData = async () => {
      try {
        const response = await fetch(url, {
          headers: { 'Content-Type': 'application/json' }, 
          method,
          body: JSON.stringify(body), 
        });

        const data = await response.json();
        setData(data);
      } catch (error) {
        setIsError(error);
      } finally {
        setIsLoading(false);
      }
    };

   if(isMounted ){
    fetchData();
   };

// cleanup function
   return () => {
    isMounted = false;
   };

  }, [url, method, body]);

  return { isLoading, data, isError };
};

export default useFetch;
```
By the way, `useEffect` cleanup function triggers an early return or short-circuiting the state update and helps fix the React memory leak warning. Because Promises cannot be canceled, the solution is to prevent the `fetchData` function call, if the component has been `unmounted` and using [lexical scoping](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Closures#lexical_scoping), we can share `isMounted` variable between the callback function and the cleanup function.

Fetching data in component using useFetch custom Hook

```javascript
const { isLoading, data, isError } = useFetch(
    "GET",
    "https://jsonplaceholder.typicode.com/posts"
  );
```

## Single Responsibility of React Components

To make your code as reusable as possible, it’s important to make your components as reusable as possible. The motto is the reduction of the complexity of the components.

Components in React have two forms `stateful` or `stateless`. The best move, in this case, is that you can have one stateful component to load data and another stateless component that can help in displaying the data. The stateless component general rule is that they can just receive props (inputs) from the parent component and return u `JSX elements`. Such components become scalable and reusable and similar to the `pure function` in JavaScript. 

Abstract away the purely presentational parts. We end up with two components, our List component, and our Item component.

```javascript
import useFetch from 'hooks/useFetch';

const List = () => {
 const { isLoading, data, isError } =
useFetch("https://jsonplaceholder.typicode.com/posts");

return (
    <>
      {isLoading && <p>Loading...</p>}
       <ul>
        {data.length > 0 && data?.map((info) => (
          <Post key={info.id} {...{info}} />
        ))}
      </ul>
    </>
  );
};

const Post = ({ img, name, author }) => {
  return (
    <li>
      <img src={img} alt={name}/>
      <div className="name">{name}</div>
      <div className="author">{author}</div>
    </li>
  );
};
```
## When to use Global vs Local State

For React state management you can choose many different solutions like a Redux, mobx, recoil, context API, etc. No hard and fast rule tells you when you should keep things in local versus global state.

Some rules for when to use global state

- Do other unrelated components in the application need access to this data? (example: username, display it in the navbar and on the welcome screen).

- Should the data be persisted as you move between pages?

- Is the same data being used in multiple components?

If the answer is yes to any of these questions, you may want to use a global state. But don’t put the `open` state of your menu inside of the global state. Try to reason about needs to be shared across your application, and what can live inside of a local component.

## A CMS enables you to add dynamic content to your React components in minutes

A modern content management system (CMS) enables content creators to manage content using a friendly dashboard while giving developers tools to deliver content to any website or app. The commonly used term, headless CMS, uses APIs (either RESTful or GraphQL) to allow developers to deliver content across various channels such as Websites, Android or IOS apps, etc. In this way, headless CMS gives teams of content creators and developers the tools each need to harness creativity quickly in a highly collaborative way. With this API-first method, a headless CMS is perfectly suited for adding dynamic content to your React application development workflow.


Try it out with [Cosmic](https://www.cosmicjs.com/) it's easy and fast.

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/h6juy5ckcsc8pg4a7mrf.png) 


Let's integrate this with our previous example using [Cosmic CMS](https://docs.cosmicjs.com/guides/react) and [SWR](https://swr.vercel.app/) React Hook for Data Fetching. Run the following command in a terminal `npm i cosmicjs swr`. Now create a file titled index.js with the following code:

```javascript
import React from 'react';
import useSWR from 'swr';
import Cosmic from 'cosmicjs';
import Post from 'components/Post';

const api = Cosmic();

// Set these values, found in Bucket > Settings after logging in at https://app.cosmicjs.com/login
const bucket = api.bucket({
  slug: 'YOUR_BUCKET_SLUG',
  read_key: 'YOUR_BUCKET_READ_KEY'
});

const fetchPosts = async () => {
  const data = await bucket.getObjects({
    query: {
      type: 'posts'
    },
    props: 'slug,title,metadata' 
  })
  return data
};

const List = () => {
 //For data fetching use SWR hook
  const { data, error } = useSWR('fetch-posts', fetchPosts);

  if (error) return <p>Failed to load</p>
  if (!data) return <p>Loading...</p>

  const posts = data.objects;

  return (
    <ul>
      {posts?.map(post => (
         <Post key={post.slug} {...{post}} />
      ))}
    </ul>
  )
};
```
---
In this article, we went over tips that will help you become a better react developer: Component imports, custom hooks, component reusability, state management and using a headless CMS, like Cosmic, will make the hand off to your content team members much easier. I add some usefule links: 

- for more information on how to use Cosmic in your React apps [Sign up for Cosmic](https://app.cosmicjs.com/signup), 

- for more info on React: [Using Hooks](https://beta.reactjs.org/learn/state-a-components-memory#recap), 
[Making Sense of React Hooks](https://dev.to/dan_abramov/making-sense-of-react-hooks-2eib), [Sharing State Between Components ](https://beta.reactjs.org/learn/sharing-state-between-components)

Thank you for reading, you can reach me out at [Twitter](https://twitter.com/naira_ge) and find me on [LinkedIn](https://www.linkedin.com/in/nairagezhoyan/). I'd love to hear your thoughts on how to improve as a React developer!