DEV Community

Kachi Cheong
Kachi Cheong

Posted on

Writing cleaner react code

As a developer, you'll often hear the phrase Clean Code. So what does it mean? Clean Code is writing code that is D.R.Y (don't repeat yourself), understandable and maintainable. This is a skill that is crucial for every developer to master.

Inexperienced react developers fall victim to repetitive code when their projects scale. So here are some good practices for React!

1 - Self Closing

Avoid using react tags more than once.

For Example:

<Example firstArg="example arg" secondArg="second arg"><Example>
Enter fullscreen mode Exit fullscreen mode

Even if they have a child property like this:

<Example>
  <h1>Text</h1>
</Example>
Enter fullscreen mode Exit fullscreen mode

You can add it as a children argument.

<Example children={<h1>Text</h1>} />
Enter fullscreen mode Exit fullscreen mode

2 - Choosing the correct function type

Use Arrow functions

Avoid using functions. In react, you'll be using variables (for example const, let or var) more often than not, so for the sake of consistency, use arrow functions.

Avoid using this.

function ExampleFunction() {
  return <h1>Hello world</h1>;
}
Enter fullscreen mode Exit fullscreen mode

Arrow functions allow you to skip a return statement for one line codes. Here is the same code as an arrow function:

// Single Line
const ExampleFunction = () => <h1>Hello world</h1>;

// Multi Line
const ExampleFunction = () => (
  <>
    <h1>Hello world</h1>
    <h2>Hello example Code</h2>
  </>
);
Enter fullscreen mode Exit fullscreen mode

Does it need to be a function?

Not every block of code needs to be a function. In fact if you're not passing an argument and all that is being returned is a JSX element, why not just make the code block a variable?

For example:

const ExampleFunction = () => <h1>Hello world</h1>;
const exampleCode = <h2>Hello example Code</h2>;

const codeBlock = (
  <>
    <ExampleFunction />
    {exampleCode}
  </>
);
Enter fullscreen mode Exit fullscreen mode

3 - Deconstruction

When you pass arguments through a function, it will look like this:

<HelloFunction firstName="John" lastName="Doe" age={18} />
Enter fullscreen mode Exit fullscreen mode

When accessing those argument properties, you'll normally do something like this:

const HelloFunction = (prop) => {
  return (
    <h1>
      Hello my name is {prop.firstName} {props.lastName}, I am {props.age}.
    </h1>
  );
};
Enter fullscreen mode Exit fullscreen mode

But by deconstructing the arguments, you avoid the repetition of props.. Here are some examples:

// Option 1 - deconstruct in the function argument
const HelloFunction = ({ firstName, lastName, age }) => (
  <h1>
    Hello my name is {firstName} {lastName}, I am {age}.
  </h1>
);

// Option 2 - deconstruct inside function
const HelloFunction = (props) => {
  const { firstName, lastName, age } = props;

  return (
    <h1>
      Hello my name is {firstName} {lastName}, I am {age}.
    </h1>
  );
};
Enter fullscreen mode Exit fullscreen mode

4 - Spreading arguments

Your return statement should be as short as possible. Here is an example of a component function:

<ExampleFunction
  firstName="John"
  lastName="Doe"
  age={18}
  address="123 example road"
  student={true}
/>
Enter fullscreen mode Exit fullscreen mode

Instead of writing all of a component function's arguments, you can declare them before and spread them like so:

const exampleArg = {
  firstName: "John",
  lastName: "Doe",
  age: 18,
  address: "123 example road",
  student: true
};

<ExampleFunction {...exampleArg} />;
Enter fullscreen mode Exit fullscreen mode

By doing this, you'll reduce the size of the files return statement.

5 - Utilize Map functions to avoid repeating.

You should avoid repetition in your code whenever possible, let's say you have a number of tabs like this:

const myTabs = () => (
  <Tabs>
    <Tab title="First Title">
      <h1>First content</h1>
    </Tab>
    <Tab title="Second Title">
      <h1>Second content</h1>
    </Tab>
    <Tab title="Third Title">
      <h1>Third content</h1>
    </Tab>
  </Tabs>
);
Enter fullscreen mode Exit fullscreen mode

Each Tab in the example above has a title and child argument. To represent the data, we can just create an array of objects for each tab. By doing this, we can map function over that object and only return the unique values for each tab.

Here is an example of how to refactor it:

const TabsData = [
  {
    title: "First Title",
    content: <h1>First content</h1>
  },
  {
    title: "Second Title",
    content: <h1>Second content</h1>
  },
  {
    title: "Third Title",
    content: <h1>Third content</h1>
  }
];

const displayedTabs = TabsData.map(({ title, content }, index) => (
  <Tab title={title} key={index}>
    <h1>{content}</h1>
  </Tab>
));

const myTabs = () => <Tabs>{displayedTabs}</Tabs>;
Enter fullscreen mode Exit fullscreen mode

This reduces errors when having tens or hundreds of tabs cause we're only changing the unique values. It also becomes a lot easier to read.

6 - Remove unnecessary files, lines and packages

Imports

If you're not using an import, comment out or remove it from your file. When you run npm start, clear any compiler warnings for example:

Compiled with warnings.

[eslint]
src/App.js
  Line 1:8:  'logo' is defined but never used  no-unused-vars

Search for the keywords to learn more about each warning.
To ignore, add // eslint-disable-next-line to the line before.

WARNING in [eslint]
src/App.js
  Line 1:8:  'logo' is defined but never used  no-unused-vars

webpack compiled with 1 warning
Enter fullscreen mode Exit fullscreen mode

When deploying, dead imports can become a nightmare, so remove or comment them out early.

Compiled successfully!

You can now view my-app in the browser.

  Local:            http://localhost:3000
  On Your Network:  http://192.168.0.75:3000

Note that the development build is not optimized.
To create a production build, use npm run build.

webpack compiled successfully
Enter fullscreen mode Exit fullscreen mode

Packages

If you are not using a specific package, uninstall it:

npm uninstall package-name
Enter fullscreen mode Exit fullscreen mode

This reduces the size of your project and which helps when collaborators clone/fork your project.

7 - Maintain a good folder structure

When your project begins to scale, it becomes harder to keep track of maintaining a good structure allow you and your colleagues to keep track of where everything is.

Here is my preferred folder structure:

Folder image

Folders

  • components - This directory should store all your global reusable components such as tabs, tables and modals
  • data - This directory should store static data (for example, your pages data)
  • pages - This directory should store all the pages for your project
  • services - This directory should store all of your data services such as api fetches
  • styles - This directory should store all of your global stylesheets
  • tests - This directory should store all of your tests

Summary

I hope you've learned something from these tips, even if you take just one of these points on board, then you're already improving by 1%. Remember these are just recommendations, if you're coding as part of a team make sure you check what they consider as acceptable practices.

Happy coding!

Top comments (0)