Five best practices for React developers

There are many ways to structure your code so it is readable, and everyone has their own way of getting there. the question becomes, Is there any best way to do this?

In this article, I’ll talk about five of the most common best practices for React developers. React was designed to be customized just the way you need it – it’s not opinion! So, if these five “best practice” scenarios don’t hold up to you, it’s totally fine to find your own approach. It’s my hope that you can get something from the way other people are currently “thinking in response.”

The best practices we’ll talk about are:

1. Directory Organization

The React documentation mentions that there are generally two main ways to organize your React applications: Group by features or routes And grouping by file type, The important thing here is not to overthink.

If you start with a small application, you can neatly organize your code as you work for yourself. Remember that React is not opinionated, so it is 100% up to you how things are structured. As long as you have a logical explanation for how the files are organized, it really doesn’t matter much.

However, since these two organization strategies are mentioned in the React documentation, let’s take a look at each one to see how they are structured. Let’s say we have an e-commerce application that has a user, a list of products, a detailed product page, a shopping cart and a checkout flow.

How can it be placed by feature?

Grouping by Features

here is the parent directory src directory, which is one of the two base directories in your React application (the public folder is the other). In src directory, we will have the root App.js And index.js files in the root of the folder. Then, we’ll have nested directories for each feature of your application.

Your move may vary as far as how things are organized: there may be more directories, fewer directories, or even more nesting in components, styling, and testing.

src/
App.js
App.css
App.test.js
index.js
global/ ⇐ items that are in common with entire application
  AppContext.js
  ThemeContext.js
  UserContext.js
  Button.js
cards/
  index.js
  Cards.css
  Cards.js
  Card.css
  Card.js
  Card.test.js
detailed-product/
    DetailedProduct.css
  DetailedProduct.js
  DetailedProduct.test.js
checkout/
  ReviewOrder.css
  ReviewOrder.js
  ReviewOrder.test.js
  ShoppingCart.css
  ShoppingCart.js
  ShoppingCart.test.js  
user/
  index.js
  User.css
  User.js
  User.test.js
enter fullscreen mode

exit fullscreen mode

Below is a convention. What might the organization look like if the files are grouped by file type?

grouping by file type

parent directory is still there src directory. Everything the client will see rendering on the screen still goes in this folder. as before we will keep App.js And index.js At the root of this directory are the files and then the directories representing the component parts of the application: components, context, CSS, hooks, and tests.

src/
App.js
index.js
components/
  App.css
  Card.js
  Cards.js
  ConfirmationPage.js
  DetailedProduct.js
  Footer.js
  Navbar.js
  ReviewOrder.js
  Settings.js
  ShoppingCart.js
  User.js
context/ 
  AppContext.js
  ThemeContext.js
  UserContext.js
css/
  Card.css
  Cards.css
  ConfirmationPage.css
  DetailedProduct.css
  Footer.css
  Navbar.css
  ReviewOrder.css
  Settings.css
  ShoppingCart.css
  User.css
hooks/
  useAuth.js
  useAxios.js
  ...other custom hooks
tests/
  App.test.js
  Card.test.js
  Cards.test.js
  ConfirmationPage.test.js
  DetailedProduct.test.js
  Footer.test.js
  Navbar.test.js
  ReviewOrder.test.js
  Settings.test.js
  ShoppingCart.test.js
  User.test.js

enter fullscreen mode

exit fullscreen mode

As before, how your project is set up depends on your application and how you want to implement it. Here the basic structure depends on what kind of file it is and nothing more. Ultimately your file structure should be made, so that it is easy to navigate. it’s up to you how you do it,

2. Components and Separation of Concerns

Before React Hooks, it was fairly easy to figure out what was considered a stateful class component versus a presentational functional component. Some developers even refer to them as “smart” components versus “dumb” components. Of course, smart components are those that carry state and handle logic, and dumb components are those that fully accept the props given to them.

After the advent of React Hooks and the update to the Context API, most everything can be considered a functional component, leading to conversations about separating components with local state, components that are not, and how to handle this. .

Ultimately, it’s up to you and/or your team how you structure your design patterns, but best practice is Keep logic and local stateful components separate from fixed components.

3. Handling State and Props

Data flow is very important in React applications. There are two ways to work with data: use of state either passing the state as prop, Let’s take a look at best practices.

State

When handling state, whether globally in the context API or locally, it should not be directly mutated by reassigning the property on the state with the new value:

 addOne = () => { //Don’t use this!!!!
   this.state.counter += 1;
 }
enter fullscreen mode

exit fullscreen mode

Instead, when treating state in class components, use this.setState() Method to update the state.

import React from "react";
import "./styles.css";

class Counter extends React.Component{
 constructor(props) {
   super(props);
   this.state = {
     counter: 0
   }
 }

 addOne = () => {
   this.setState({counter: this.state.counter + 1})
 }

 subtractOne = () => {
   this.setState({counter: this.state.counter - 1});
 }

 reset = () => {
   this.setState({ counter: 0 });
 }
 render() {
   return (
     <div className="App">
       <h1>Simple React Counter</h1>
       <h2>{this.state.counter}</h2>
       <button onClick={this.addOne}> + </button>
       <button onClick={this.reset}> Reset </button>
       <button onClick={this.subtractOne}> - </button>
     </div>
   );
 }
}

export default Counter;
enter fullscreen mode

exit fullscreen mode

when using response hookyou’ll use whatever your name is set method:

import React, { useState } from "react";
import "./styles.css";

export default function App(){

 const [ counter, setCounter ] = useState(0);
 const addOne = () => {
   setCounter(counter + 1)
 }

 const subtractOne = () => {
   setCounter(counter - 1);
 }

 const reset = () => {
   setCounter(0);
 }
   return (
     <div className="App">
       <h1>Simple React Counter</h1>
       <h2>{counter}</h2>
       <button onClick={subtractOne}> - </button>
       <button onClick={reset}> Reset </button>
       <button onClick={addOne}> + </button>

     </div>
   );
}

enter fullscreen mode

exit fullscreen mode

props

When working with props and passing state to other components to be used, there may come a point where you need to pass props to five children. This method of passing from parent to child over several generations is called prop drilling and should be avoided.

While the code will certainly work if you pass props across multiple generations, it is prone to bugs, and it can be hard to follow the flow of data. It is best if you need to provide access to the state to children for several generations. you should build some kind Design Patterns for Global State Management With Redux or Context API (currently simpler, more preferred way with Context API).

but do study more react design pattern In this article- Introduction to React Design Patterns: Flux, Redux and Context API

4. intangible

the reaction flourishes reuse, When talking about React best practices, the word abstract comes up a lot. Abstraction means there are parts of a larger component or application that can be abstracted away, made into their own functional component, and then Imported in large component, Making a component as simple as possible, often it serves only one purpose, increases your chances of the code being reusable.

In the simple counter application created above, there are opportunities to remove certain elements from the app component. The buttons can be abstracted into their own component where we pass the method and the button label as props.

The header and title of the application can also go into their own components. The app component might look something like this after we’ve removed everything:

import React, { useState } from "react";

import { Button } from "./Button";
import { Display } from "./Display";
import { Header } from "./Header";
import "./styles.css";

export default function App(){
  const addOne = () => {
   setCounter(counter + 1)
 }

 const subtractOne = () => {
   setCounter(counter - 1);
 }

 const reset = () => {
   setCounter(0);
 }

 const initialState = [
   {operation: subtractOne, buttonLabel:"-"},
   {operation: reset, buttonLabel: "reset"},
   {operation: addOne, buttonLabel: "+"}
 ]
 const [ counter, setCounter ] = useState(0);
 const [ buttonContents,  ] = useState(initialState)
    return (
     <div className="App">
       <Header header="Simple React Counter"/>
       <Display counter={counter}/>
       {buttonContents.map(button => {
         return (
           <Button key={button.operation + button.buttonLabel} operation={button.operation} buttonLabel={button.buttonLabel} />
         )
       })}
     </div>
   );
}

enter fullscreen mode

exit fullscreen mode

The main purpose of abstraction is to make the child components as generic as possible so that they can be reused as per your requirement. The app component should only contain all information that is specific to the application and should only render or return smaller components.

5. Naming Convention

There are three main naming conventions in React that should be considered best practice.

  1. Components must be PascalCase – CamelCase is also capitalized and named for their function, not specific application feature (if you change it later).

  2. Elements that require keys must be unique, non-random identifiers (such as individual cards or entries in a card deck or list). It’s best practice to not just use indexes for keys. It is legal to have a key assignment that is made up of a combination of two different object properties.

The basic purpose of the key is to store basic information so that React knows what has changed in the application.

key={button.operation + button.buttonLabel} 
enter fullscreen mode

exit fullscreen mode

  1. Methods must be in camelcase and named for their function And doesn’t have to be application specific. For the same reasons that components are in PascalCase, methods should be named for their purpose and not their attribute in the application.

Wrapping Up and Next Steps

In this article, we have covered five best practices to employ in React Development. For many of these cases, it’s more about what works for you and your team, as opposed to what is specifically considered “best practice”.

remember: React doesn’t care how you pass the data – it just cares what you do.

It is the developers who later edit and read your code who will need to be able to understand and improve your contributions.

I hope this article has helped you in your feedback journey. Keep learning React and stay updated with all its updates. View Instructional Courses Feedback for front-end developers To build highly interactive, professional-quality apps using React.

Happy Learning!

Continue reading about React on Educative

start a discussion

Which of these best practices have you found most helpful? Was this article helpful? Let us know in the comments below!

Leave a Comment