---
title: Millors pràctiques
image: /images/user-guide/tips/light-bulb.png
---

<Frame>
  <img src="/images/user-guide/tips/light-bulb.png" alt="Header" />
</Frame>

Aquest document descriu les millors pràctiques que hauries de seguir quan treballis al frontend.

## Gestió d'estat

React and Recoil handle state management in the codebase.

### Utilitza `useRecoilState` per emmagatzemar l'estat.

És una bona pràctica crear tants àtoms com necessitis per emmagatzemar el teu estat.

<Warning>

És millor utilitzar àtoms addicionals que intentar ser massa concís amb el drilling de props.

</Warning>

```tsx
export const myAtomState = atom({
  key: 'myAtomState',
  default: 'default value',
});

export const MyComponent = () => {
  const [myAtom, setMyAtom] = useRecoilState(myAtomState);

  return (
    <div>
      <input
        value={myAtom}
        onChange={(e) => setMyAtom(e.target.value)}
      />
    </div>
  );
}
```

### No utilitzis `useRef` per emmagatzemar l'estat.

Evita utilitzar `useRef` per emmagatzemar l'estat.

Si vols emmagatzemar l'estat, hauries d'utilitzar `useState` o `useRecoilState`.

Consulta [com gestionar les re-renderitzacions](#managing-re-renders) si sents que necessites `useRef` per evitar que algunes re-renderitzacions passin.

## Gestionar les re-renderitzacions

Les re-renderitzacions poden ser difícils de gestionar en React.

Aquí tens algunes normes a seguir per evitar re-renderitzacions innecessàries.

Recorda que **sempre** pots evitar re-renderitzacions comprenent-ne la causa.

### Treballa a nivell de base

Evitar les re-renderitzacions en noves funcionalitats ara és fàcil eliminant-les a nivell de base.

El component sidecar `PageChangeEffect` conté només un `useEffect` que manté tota la lògica per executar en un canvi de pàgina.

D'aquesta manera, saps que només hi ha un lloc que pot provocar una re-renderització.

### Pensa dues vegades abans d'afegir `useEffect` en la teva base de codi.

Les re-renderitzacions són sovint provocades per `useEffect` innecessaris.

Hauries de considerar si necessites `useEffect`, o si pots moure la lògica en una funció de gestió d'esdeveniments.

En general, trobaràs que és fàcil moure la lògica a una funció `handleClick` o `handleChange`.

També els pots trobar a llibreries com Apollo: `onCompleted`, `onError`, etc.

### Utilitza un component germà per extreure la lògica de `useEffect` o de recuperació de dades.

Si sents que necessites afegir un `useEffect` en el teu component de base, hauríes de considerar extreur-lo a un component sidecar.

Pots aplicar el mateix per a la lògica de recuperació de dades, amb els hooks d'Apollo.

```tsx
// ❌ Bad, will cause re-renders even if data is not changing, 
//    because useEffect needs to be re-evaluated
export const PageComponent = () => {
  const [data, setData] = useRecoilState(dataState);
  const [someDependency] = useRecoilState(someDependencyState);

  useEffect(() => {
    if(someDependency !== data) {
      setData(someDependency);
    }
  }, [someDependency]);

  return <div>{data}</div>;
};

export const App = () => (
  <RecoilRoot>
    <PageComponent />
  </RecoilRoot>
);
```

```tsx
// ✅ Good, will not cause re-renders if data is not changing, 
//   because useEffect is re-evaluated in another sibling component
export const PageComponent = () => {
  const [data, setData] = useRecoilState(dataState);

  return <div>{data}</div>;
};

export const PageData = () => {
  const [data, setData] = useRecoilState(dataState);
  const [someDependency] = useRecoilState(someDependencyState);

  useEffect(() => {
    if(someDependency !== data) {
      setData(someDependency);
    }
  }, [someDependency]);

  return <></>;
};

export const App = () => (
  <RecoilRoot>
    <PageData />
    <PageComponent />
  </RecoilRoot>
);
```

### Utilitza estats de família Recoil i selectors de família Recoil.

Els estats de família Recoil i els selectors són una gran manera d'evitar re-renderitzacions.

Són útils quan necessites emmagatzemar una llista d'objectes.

### No hauries d'utilitzar `React.memo(MyComponent)`

Evita utilitzar `React.memo()` perquè no soluciona la causa de la re-renderització, sinó que trenca la cadena de re-renderitzacions, la qual cosa pot portar a comportaments inesperats i fer que el codi sigui molt difícil de refactoritzar.

### Limita l'ús de `useCallback` o `useMemo`

Sovint no són necessaris i faran que el codi sigui més difícil de llegir i mantenir per un guany de rendiment que és imperceptible.

## Console.logs

Les declaracions `console.log` són valuoses durant el desenvolupament, oferint informació en temps real sobre valors de variables i flux de codi. Però, deixar-les en codi de producció pot portar a diversos problemes:

1. **Rendiment**: Un registre excessiu pot afectar el rendiment en temps d'execució, especialment en aplicacions del costat del client.

2. **Seguretat**: Registre de dades sensibles pot exposar informació crítica a qualsevol que inspeccioni la consola del navegador.

3. **Neteja**: Omplir la consola amb registres pot enfosquir advertències o errors importants que els desenvolupadors o eines necessiten veure.

4. **Professionalitat**: Els usuaris finals o clients que revisen la consola veient una miríada de declaracions de registre podrien qüestionar la qualitat i el detall del codi.

Assegura't d'eliminar tots els `console.log` abans d'empènyer el codi cap a producció.

## Nomenclatura

### Nomenclatura de variables

Els noms de variable han de representar de manera precisa el propòsit o la funció de la variable.

#### El problema amb els noms genèrics

Els noms genèrics en programació no són ideals perquè manquen d'especificitat, portant a ambigüitat i una menor llegibilitat del codi. Aquests noms no aconsegueixen transmetre el propòsit de la variable o funció, fent que sigui un desafiament per als desenvolupadors comprendre la intenció del codi sense una investigació més profunda. Això pot resultar en un augment del temps de depuració, una major susceptibilitat a errors i dificultats en manteniment i col·laboració. Mentrestant, la nomenclatura descriptiva fa que el codi sigui autoexplicatiu i més fàcil de navegar, millorant la qualitat del codi i la productivitat del desenvolupador.

```tsx
// ❌ Bad, uses a generic name that doesn't communicate its
//    purpose or content clearly
const [value, setValue] = useState('');
```

```tsx
// ✅ Good, uses a descriptive name
const [email, setEmail] = useState('');
```

#### Algunes paraules per evitar en noms de variables.

- dummy

### Gestionadors d'esdeveniments

Els noms dels gestionadors d'esdeveniments haurien de començar amb `handle`, mentre que `on` és un prefix utilitzat per anomenar esdeveniments en prop de components.

```tsx
// ❌ Bad
const onEmailChange = (val: string) => {
  // ...
};
```

```tsx
// ✅ Good
const handleEmailChange = (val: string) => {
  // ...
};
```

## Props opcionals

Evita passar el valor per defecte per a un prop opcional.

**EXEMPLE**

Pren el component `EmailField` definit a continuació:

```tsx
type EmailFieldProps = {
  value: string;
  disabled?: boolean;
};

const EmailField = ({ value, disabled = false }: EmailFieldProps) => (
  <TextInput value={value} disabled={disabled} fullWidth />
);
```

**Ús**

```tsx
// ❌ Bad, passing in the same value as the default value adds no value
const Form = () => <EmailField value="username@email.com" disabled={false} />;
```

```tsx
// ✅ Good, assumes the default value
const Form = () => <EmailField value="username@email.com" />;
```

## Component com a props

Intenta tant com sigui possible passar components no instanciats com a 'props', perquè els fills puguin decidir per si mateixos quines 'props' necessiten passar.

L'exemple més comú d'això són els components d'icones:

```tsx
const SomeParentComponent = () => <MyComponent Icon={MyIcon} />;

// In MyComponent
const MyComponent = ({ MyIcon }: { MyIcon: IconComponent }) => {
  const theme = useTheme();

  return (
    <div>
      <MyIcon size={theme.icon.size.md}>
    </div>
  )
};
```

Perquè React entengui que el component és un component, necessites usar PascalCase, per després instanciar-lo amb `<MyIcon>`

## Canalització de Prop: Mantingues-ho al Mínim

La canalització de 'props', en el context de React, es refereix a la pràctica de passar variables d'estat i les seves assignacions a través de moltes capes de components, fins i tot si els components intermediaris no les utilitzen. Encara que de vegades és necessari, l'ús excessiu de la canalització de 'props' pot conduir a:

1. **Menor Llegibilitat**: Seguir d'on prové una 'prop' o on s'utilitza pot complicar-se en una estructura de components profundament niuada.

2. **Reptes de Manteniment**: Els canvis en l'estructura de 'props' d'un component poden requerir ajustaments en diversos components, encara que no facin servir directament la 'prop'.

3. **Menor Reutilització del Component**: Un component que rep moltes 'props' només per passar-les avall es torna menys de propòsit general i més difícil de reutilitzar en diferents contextos.

Si sents que estàs utilitzant excessivament la canalització de 'props', consulteu [millors pràctiques de gestió d'estat](#state-management).

## Importacions

Quan importis, opta per utilitzar els àlies designats en lloc d'especificar camins complets o relatius.

**Els Àlies**

```js
{
  alias: {
    "~": path.resolve(__dirname, "src"),
    "@": path.resolve(__dirname, "src/modules"),
    "@testing": path.resolve(__dirname, "src/testing"),
  },
}
```

**Ús**

```tsx
// ❌ Bad, specifies the entire relative path
import {
  CatalogDecorator
} from '../../../../../testing/decorators/CatalogDecorator';
import {
  ComponentDecorator
} from '../../../../../testing/decorators/ComponentDecorator';
```

```tsx
// ✅ Good, utilises the designated aliases
import { CatalogDecorator } from '~/testing/decorators/CatalogDecorator';
import { ComponentDecorator } from 'twenty-ui/testing';
```

## Validació d'Esquema

[Zod](https://github.com/colinhacks/zod) és el verificador d'esquema per a objectes no tipats:

```js
const validationSchema = z
  .object({
    exist: z.boolean(),
    email: z
      .string()
      .email('Email must be a valid email'),
    password: z
      .string()
      .regex(PASSWORD_REGEX, 'Password must contain at least 8 characters'),
  })
  .required();

type Form = z.infer<typeof validationSchema>;
```

## Canvis Rellevants

Realitza sempre proves manuals exhaustives abans de procedir per garantir que les modificacions no hagin causat disrupcions en altres parts, donat que les proves encara no s'han integrat àmpliament.

