---
title: Beste praksis
image: /images/user-guide/tips/light-bulb.png
---

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

Dette dokumentet skisserer de beste praksisene du bør følge når du jobber på frontend.

## Tilstandshåndtering

React og Recoil håndterer tilstandshåndtering i kodebasen.

### Bruk `useRecoilState` for å lagre tilstand

Det er en god praksis å lage så mange atomer som du trenger for å lagre tilstanden din.

<Warning>

Det er bedre å bruke ekstra atomer enn å prøve å være for konsis med å bore 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>
  );
}
```

### Ikke bruk `useRef` for å lagre tilstand

Unngå å bruke `useRef` for å lagre tilstand.

Hvis du vil lagre tilstand, bør du bruke `useState` eller `useRecoilState`.

Se [hvordan håndtere omrendringer](#managing-re-renders) hvis du føler at du trenger `useRef` for å forhindre at noen omrendringer skjer.

## Håndtere omrendringer

Omrendringer kan være vanskelige å håndtere i React.

Her er noen regler å følge for å unngå unødvendige omrendringer.

Husk at du **alltid** kan unngå omrendringer ved å forstå deres årsak.

### Arbeid på rotnivå

Unngåelse av omrendringer i nye funksjoner er nå gjort enkelt ved å eliminere dem på rotnivå.

The `PageChangeEffect` sidecar component contains just one `useEffect` that holds all the logic to execute on a page change.

På denne måten vet du at det er bare ett sted som kan utløse en omrendering.

### Tenk deg nøye om før du legger til `useEffect` i din kodebase

Omrendringer er ofte forårsaket av unødvendig `useEffect`.

Du bør vurdere om du trenger `useEffect`, eller om du kan flytte logikken til en hendelseshåndtererfunksjon.

Du vil generelt finne det enkelt å flytte logikken til en `handleClick` eller `handleChange`-funksjon.

Du kan også finne dem i biblioteker som Apollo: `onCompleted`, `onError`, osv.

### Bruk en søskenkomponent for å trekke ut `useEffect` eller datahentingslogikk

Hvis du føler at du trenger å legge til en `useEffect` i din rotkomponent, bør du vurdere å trekke den ut i en sidevognkomponent.

Du kan bruke det samme for datahentingslogikk, 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>
);
```

### Bruk recoil familietilstander og recoil familieselektorer

Recoil familietilstander og selektorer er en flott måte å unngå omrendringer på.

De er nyttige når du trenger å lagre en liste over elementer.

### Du bør ikke bruke `React.memo(MyComponent)`

Unngå bruk av `React.memo()` fordi det ikke løser årsaken til omrenderingen, men i stedet bryter omrenderingskjeden, noe som kan føre til uventet oppførsel og gjøre koden veldig vanskelig å refaktorere.

### Begrens bruken av `useCallback` eller `useMemo`

De er ofte ikke nødvendige og vil gjøre koden vanskeligere å lese og vedlikeholde for en gevinst i ytelse som er umerkelig.

## Console.logs

`console.log` setninger er verdifulle under utvikling, og tilbyr sanntidsinnsikt i variabelverdier og kodeflyt. Men å la dem være i produksjonskode kan føre til flere problemer:

1. **Ytelse**: Overdreven logging kan påvirke kjøringsytelsen, spesielt på klientapplikasjoner.

2. **Sikkerhet**: Logging av sensitiv data kan avsløre kritisk informasjon til alle som inspiserer nettleserens konsoll.

3. **Ryddighet**: Å fylle opp konsollen med logger kan skjule viktige advarsler eller feil som utviklere eller verktøy trenger å se.

4. **Profesjonalitet**: Sluttbrukere eller kunder som sjekker konsollen og ser en mengde loggutsagn kan stille spørsmål ved kvaliteten og finishen av koden.

Forsikre deg om at du fjerner alle `console.logs` før du skyver koden til produksjon.

## Navngiving

### Variabelnavngiving

Variabelnavn bør presist beskrive variablens hensikt eller funksjon.

#### Problemet med generiske navn

Generiske navn i programmering er ikke ideelle fordi de mangler spesifisitet, noe som fører til tvetydighet og redusert kodelesbarhet. Slike navn klarer ikke å formidle variabelen eller funksjonens hensikt, noe som gjør det utfordrende for utviklere å forstå kodenes intensjon uten dypere undersøkelser. Dette kan føre til økt feilsøkingstid, høyere sårbarhet for feil, og vansker ved vedlikehold og samarbeid. I mellomtiden gjør beskrivende navngiving koden selvforklarende og lettere å navigere, og øker kodekvaliteten og utviklerens produktivitet.

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

#### Noen ord å unngå i variabelnavn

- dummy

### Hendelseshåndterere

Hendelseshåndterernes navn bør starte med `handle`, mens `on` er et prefiks brukt for å navngi hendelser i komponentprops.

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

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

## Valgfrie Props

Unngå å sende den standardverdien for en valgfri prop.

**EKSEMPEL**

Ta `EmailField` komponenten definert nedenfor:

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

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

**Bruk**

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

Prøv så mye som mulig å sende ikke-instanserte komponenter som props, slik at barn kan bestemme selv hvilke props de trenger å sende.

Det vanligste eksemplet på dette er ikonekomponenter.

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

For at React skal forstå at komponenten er en komponent, må du bruke store bokstaver, for senere å instansiere den med `<MyIcon>`

## Prop-gjennomgang: Hold det minimalt

I React-sammenheng refererer prop-gjennomgang til praksisen med å sende tilstandsvariabler og deres settere gjennom mange komponentlag, selv om mellomliggende komponenter ikke bruker dem. Selv om det noen ganger er nødvendig, kan overdreven prop-gjennomgang føre til:

1. **Redusert Lesbarhet**: Å spore hvor en prop stammer fra eller hvor den brukes kan bli komplisert i en dypt nestet komponentstruktur.

2. **Vedlikeholdsutfordringer**: Endringer i en komponents prop-struktur kan kreve justeringer i flere komponenter, selv om de ikke direkte bruker propen.

3. **Redusert Komponentgjenbruk**: En komponent som mottar mange props kun for å sende dem videre blir mindre allsidig og vanskeligere å gjenbruke i forskjellige sammenhenger.

Hvis du føler at du bruker overdreven prop-gjennomgang, se [beste praksis for tilstandshåndtering](#state-management).

## Importer

Ved import, velg de angitte aliasene fremfor å spesifisere komplette eller relative stier.

**Håndtak Aliaser**

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

**Bruk**

```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) er skjema-valideren for utypede objekter.

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

## Kritiske Endringer

Utfør alltid grundig manuell testing før du går videre for å sikre at modifikasjoner ikke har forårsaket forstyrrelser andre steder, gitt at tester ennå ikke er omfattende integrert.

