---
title: Bästa praxis
image: /images/user-guide/tips/light-bulb.png
---

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

Detta dokument beskriver de bästa praxis du bör följa när du arbetar med frontend.

## Tillståndshantering

React och Recoil hanterar tillståndshantering i kodbasen.

### Använd `useRecoilState` för att lagra tillstånd

Det är god praxis att skapa så många atomer som du behöver för att lagra ditt tillstånd.

<Warning>

Det är bättre att använda extra atomer än att försöka vara för koncis med prop drilling.

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

### Använd inte `useRef` för att lagra tillstånd

Undvik att använda `useRef` för att lagra tillstånd.

Om du vill lagra tillstånd, borde du använda `useState` eller `useRecoilState`.

Se [hur man hanterar om-återgivningar](#managing-re-renders) om du känner att du behöver `useRef` för att förhindra vissa om-återgivningar från att hända.

## Hantering av om-återgivningar

Om-återgivningar kan vara svåra att hantera i React.

Här är några regler att följa för att undvika onödiga om-återgivningar.

Tänk på att du **alltid** kan undvika om-återgivningar genom att förstå orsaken till dem.

### Work at the root level

Att undvika om-återgivningar i nya funktioner är nu enkelt genom att eliminera dem på rotnivå.

Den `PageChangeEffect` sidovagnskomponent innehåller bara en `useEffect` som håller all logik för att utföra vid en sidbyte.

På det sättet vet du att det bara finns en plats som kan trigga en om-återgivning.

### Tänk alltid två gånger innan du lägger till `useEffect` i din kodbas

Om-återgivningar orsakas ofta av onödig `useEffect`.

Du bör tänka på om du behöver `useEffect`, eller om du kan flytta logiken till en event handler funktion.

Du kommer i allmänhet tycka att det är enkelt att flytta logiken till en `handleClick` eller `handleChange` funktion.

Du kan också hitta dem i bibliotek som Apollo: `onCompleted`, `onError`, etc.

### Använd en syskonkomponent för att extrahera `useEffect` eller informationshämtning logik

Om du känner att du behöver lägga till en `useEffect` i din rotkomponent, bör du överväga att extrahera den i en sidovagnskomponent.

Du kan använda samma för informationshämtning logik, med Apollo hooks.

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

### Använd recoil familjetillstånd och recoil familje selectors

Recoil familjetillstånd och selectors är ett bra sätt att undvika om-återgivningar.

De är användbara när du behöver lagra en lista över objekt.

### Du borde inte använda `React.memo(MyComponent)`

Undvik att använda `React.memo()` eftersom det inte löser orsaken till om-återgivningen, utan istället bryter återgivningskedjan, vilket kan leda till oväntat beteende och göra koden mycket svår att refaktorisera.

### Begränsa användning av `useCallback` eller `useMemo`

De är ofta inte nödvändiga och gör koden svårare att läsa och underhålla för en prestationsökning som är obetydlig.

## Console.logs

`console.log` uttalanden är värdefulla under utveckling och ger realtidsinsikter i variablervärden och kodens flöde. Men att lämna dem i produktionskod kan leda till flera problem:

1. **Prestanda**: Överdriven loggning kan påverka körtiden, särskilt i klientapplikationer.

2. **Säkerhet**: Loggning av känslig data kan exponera kritisk information för alla som inspekterar webbläsarens konsol.

3. **Renhet**: Att fylla konsolen med loggar kan dölja viktiga varningar eller fel som utvecklare eller verktyg behöver se.

4. **Professionalism**: Slutanvändare eller kunder som kollar konsolen och ser en mängd loggutdrag kan ifrågasätta kodens kvalitet och finish.

Se till att du tar bort alla `console.logs` innan koden trycks till produktion.

## Namngivning

### Variabelnamngivning

Variabelnamn bör korrekt avspegla variabelns syfte eller funktion.

#### Problemet med generiska namn

Generiska namn i programmering är inte idealiska eftersom de saknar specifikhet, vilket leder till oklarheter och minskad kodläsbarhet. Sådana namn misslyckas med att förmedla variabelns eller funktionens syfte, vilket gör det svårt för utvecklare att förstå kodens avsikt utan djupare granskning. Detta kan leda till ökad felsökningstid, högre känslighet för fel och svårigheter i underhåll och samarbete. Medan beskrivande namngivning gör koden självförklarande och lättare att navigera, vilket förbättrar kodkvalitet och utvecklarproduktivitet.

```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('');
```

#### Några ord att undvika i variabelnamn

- dummy

### Eventhanterare

Namn på eventhanterare borde börja med `handle`, medan `on` är ett prefix som används för att namnge events i komponenters prop.

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

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

## Valfria Props

Undvik att skicka in standardvärdet för en valfri prop.

**EXEMPEL**

Ta `EmailField`-komponenten definierad nedan:

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

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

**Användning**

```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" />;
```

## Komponent som props

Försök så mycket som möjligt att skicka oinstanserade komponenter som props, så barn kan själva bestämma vilka props de behöver skicka.

Det vanligaste exemplet för det är ikonkomponenter:

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

För att React ska förstå att komponenten är en komponent, måste du använda PascalCase, för att senare instansiera den med `<MyIcon>`

## Prop borrning: Håll det minimalt

Prop borrning, i React kontext, avser praktiken att skicka tillståndsvariabler och deras upprättare genom många lager av komponenter, även om mellanhandkomponenter inte använder dem. Även om det ibland är nödvändigt, kan överdriven prop borrning leda till:

1. **Minskad läsbarhet**: Att spåra varifrån en prop härstammar eller används kan bli komplicerat i en djupt nästad komponentstruktur.

2. **Underhållsutmaningar**: Förändringar i en komponents prop-struktur kan kräva justeringar i flera komponenter, även om de inte direkt använder prop.

3. **Minskad komponent-återanvändbarhet**: En komponent som tar emot många props enbart för att skicka dem vidare blir mindre allmän och svårare att återanvända i olika kontexter.

Om du känner att du använder överdriven prop borrning, se [bästa praxis för tillståndshantering](#state-management).

## Importera

Vid import, välj de designade aliaserna istället för att specificera kompletta eller relativa sökvägar.

**Aliaserna**

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

**Användning**

```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';
```

## Schema validering

[Zod](https://github.com/colinhacks/zod) är schema valideraren för otydade objekt:

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

## Brytande förändringar

Utför alltid noggranna manuella tester innan du går vidare för att garantera att ändringar inte har orsakat störningar någon annanstans, eftersom tester ännu inte har integrerats i stor omfattning.

