Good Practices for Frontend with React.js
Tags: typescript, productivity, frontend, react
Published: 2023-04-04 12:58:51

## 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
```typescript
interface TextInputProps {
 placeholder?: string;
}

export function TextInput({ placeholder: TextInputProps}){
 return (
  <input placeholder={placeholder} />
 )
}
```

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
```typescript
interface TextInputProps extends InputHTMLAttributes<HTMLInputElement>{}

export function TextInput({ props: TextInputProps}){
 return (
  <input {...props} />
 )
}
```
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:

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

console.log(uniqueArray) // ['Bahia', 'Vitória']
```

---
## 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.

```typescript
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
*/
```

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._

```typescript
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
*/
```
### Recommended approaches:

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

```typescript
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
*/
```

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.

```typescript
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>
  );
};
```

---
## 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_

```typescript
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>;
}
```

---
**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!