DEV Community

Cover image for Good Practices for Frontend with React.js
Jean Vidal
Jean Vidal

Posted on • Updated on

Good Practices for Frontend with React.js

Introduction

As is a common knowledge, in programing don't exist only one way of programming, because each developer has its own characteristics.

Although that is so, after uncountable systems developed and problems of different scenarios solved, the way was cleared for small but effective practices.

So I'll explore some of these best practices below, so that we can leverage them and turn our software more readable, clean and reusable.


Passing properties from a parent element to a child element

One of the things we developers will be doing most is building components and passing properties, however, there are more efficient ways to do it.

I brought two examples, one recommended and other not.

Not recommended approach

interface TextInputProps {
 placeholder?: string;
}

export function TextInput({ placeholder: TextInputProps}){
 return (
  <input placeholder={placeholder} />
 )
}
Enter fullscreen mode Exit fullscreen mode

But.. why not?

There are many native properties in the input element, and that way, whenever it was necessary to use some native property, it would have to be added in props as a parameter.

So.. what would be the best way?

Recommended approach

interface TextInputProps extends InputHTMLAttributes<HTMLInputElement>{}

export function TextInput({ props: TextInputProps}){
 return (
  <input {...props} />
 )
}
Enter fullscreen mode Exit fullscreen mode

With props inheriting - extends - the HTML attributes of a generic, can be use the spread operator to pass these properties to the child element within the component.


Removing duplicate values in an array

Another very common activity is remove duplicate values.
I present to you a very useful resource: Set.

The Set allows you to store unique values of any type and with the spread operator, we can solve this way:

const arr = [ 'Bahia', 'Bahia', 'Vitória', 'Vitória' ]
const uniqueArray = [ ...new Set(arr) ]

console.log(uniqueArray) // ['Bahia', 'Vitória']
Enter fullscreen mode Exit fullscreen mode

Assigning a key when rendering a .map()

When displaying a list, is very common receive a error message - Each child in an array should have a unique "key" prop. - which indicates the need to create a unique key for each element.

This key must have two characteristics:

  • Unique - It cannot be identical to any sibling element.
  • Static - Must not change between render events.

Caveat: If the index doesn't matter for your iteration and you are just putting it in for the error message, then it's not a problem.

Now let's get to the examples!

Approaches not recommended:

The most common mistake is set the iteration's index as a key, but this breaks the characteristic of being static, because if we add a new element in the list, the index will be change.

const App = () => {
  let rows = [1, 2, 3, 4];
  return (
    <div>
      {rows.map((row,i) => (
        <div key={i}>{`${row}: ${i}`}</div>
      ))}
    </div>
  );
};
/*
Output:
 1: 0
 2: 1
 3: 2
 4: 3
*/
Enter fullscreen mode Exit fullscreen mode

Since the index can't, then I will set random values!

It will probably guarantee unique values, but it will force to render each item even when not requested, directly affecting the performance.

Obs.: It doesn't remove the possibility of duplicate values.

const App = () => {
  let rows = [1, 2, 3, 4];
  return (
    <div>
      {rows.map((row) => (
        <div key={Math.random()}>{`${row}: ${Math.random()}`}</div>
      ))}
    </div>
  );
};
/*
Output:
 1: 0.17787081878683653
 2: 0.23435869336795734
 3: 0.474942799444668
 4: 0.8308284387098894
*/
Enter fullscreen mode Exit fullscreen mode

Recommended approaches:

The ideal scenario is that the list contains unique identifiers that can be used as a key.

const App = () => {
  let rows = [
  { id: 1, value: 'val 1' },
  { id: 2, value: 'val 2' },
  { id: 3, value: 'val 3' },
  { id: 4, value: 'val 4' },
 ];

  return (
    <div>
      {rows.map((row) => (
        <div key={row.id}>{`${row.value}: ${row.id}`}</div>
      ))}
    </div>
  );
};

/*
Output:
 val 1: 1
 val 2: 2
 val 3: 3
 val 4: 4
*/
Enter fullscreen mode Exit fullscreen mode

But if it doesn't have?

In this scenario is important to generate a unique identifier before iterating the list. The most indicated moment is when the component is being mounted, but care must still be taken so that it is not executed again in a rendering.

const App = () => {
  let rows = [1, 2, 3, 4];

 let rows = rows.map(item => { 
   return {uid: algumaBiblioteca.geraIdUnico(), value: item};
 });

  return (
    <div>
      {rows.map((row) => (
        <div key={row.uid}>{`${row.value}: ${row.uid}`}</div>
      ))}
    </div>
  );
};
Enter fullscreen mode Exit fullscreen mode

Recommended typings for use as a properties with TypeScript

Knowing which data type of component's property is a very common doubt for anyone who uses TypeScript.

For those who don't have much patience, an any or unkown will solve.

But be careful!

If we are using TypeScript to type our components and properties, why are we putting a generic type on everything?

This apparently solves the problem of laziness,but it misses out on valuable resources each type has to offer.

Below i will list the most common types, apart from the primitives ones, that can help with a quick decision.

But remembering!! There is no silver bullet, so, it is important to evaluate each case individually

interface Props {
  /** Função normal que não recebe ou retorna nada. */
  onClick: () => void;
  onClickWithSpecificEvent: () => (event: React.MouseEvent<HTMLButtonElement>) => void;
  onClickWithParameter(event: React.MouseEvent<HTMLButtonElement>): void;
  onChangeWithParameter: (id: number) => void;
  onChangeWithParameterAndSpecificEvent: (event: React.ChangeEvent<HTMLInputElement>) => void;
  generalReactElements: ReactNode;
  singleReactElement: JSX.Element;
  style: React.CSSProperties;
  setState: React.Dispatch<React.SetStateAction<number>>;
  propsWithAllPropsOfButtonAndWithoutRef: Props & React.ComponentPropsWithoutRef<"button">;
  propsWithAllPropsOfRef: Props &React.ComponentPropsWithRef<MyButtonWithForwardRef>;
}
Enter fullscreen mode Exit fullscreen mode

That's it for now!

These were a little "tricks" that can make a difference in code quality.

Always assess the real need and understand the benefits of using each resource. This goes for everything, be it good practices, patterns, etc.

See you next!

Top comments (0)