Created by Github action --------- Co-authored-by: Crowdin Bot <support+bot@crowdin.com> Co-authored-by: github-actions <github-actions@twenty.com>
296 lines
9.0 KiB
Plaintext
296 lines
9.0 KiB
Plaintext
---
|
|
title: Guia d'estil
|
|
image: /images/user-guide/notes/notes_header.png
|
|
---
|
|
|
|
<Frame>
|
|
<img src="/images/user-guide/notes/notes_header.png" alt="Header" />
|
|
</Frame>
|
|
|
|
Aquest document inclou les regles a seguir quan s'escriu codi.
|
|
|
|
L'objectiu aquí és tenir una base de codi consistent, que sigui fàcil de llegir i fàcil de mantenir.
|
|
|
|
Per això, és millor ser una mica més verbós que ser massa concís.
|
|
|
|
Tingueu sempre present que la gent llegeix codi més sovint del que l'escriu, especialment en un projecte de codi obert, on tothom pot contribuir.
|
|
|
|
Hi ha moltes regles que no es defineixen aquí, però que es verifiquen automàticament amb linters.
|
|
|
|
## React
|
|
|
|
### Utilitzeu components funcionals
|
|
|
|
Feu servir sempre components funcionals TSX.
|
|
|
|
No utilitzeu `import` predeterminat amb `const`, perquè és més difícil de llegir i més difícil d'importar amb l'autocompletar de codi.
|
|
|
|
```tsx
|
|
// ❌ Bad, harder to read, harder to import with code completion
|
|
const MyComponent = () => {
|
|
return <div>Hello World</div>;
|
|
};
|
|
|
|
export default MyComponent;
|
|
|
|
// ✅ Good, easy to read, easy to import with code completion
|
|
export function MyComponent() {
|
|
return <div>Hello World</div>;
|
|
};
|
|
```
|
|
|
|
### Props
|
|
|
|
Creeu el tipus de les props i anomeneu-les `(NomDelComponent)Props` si no cal exportar-les.
|
|
|
|
Utilitzeu l'estructuració de props.
|
|
|
|
```tsx
|
|
// ❌ Bad, no type
|
|
export const MyComponent = (props) => <div>Hello {props.name}</div>;
|
|
|
|
// ✅ Good, type
|
|
type MyComponentProps = {
|
|
name: string;
|
|
};
|
|
|
|
export const MyComponent = ({ name }: MyComponentProps) => <div>Hello {name}</div>;
|
|
```
|
|
|
|
#### Absteniu-vos d'utilitzar `React.FC` o `React.FunctionComponent` per definir tipus de props
|
|
|
|
```tsx
|
|
/* ❌ - Bad, defines the component type annotations with `FC`
|
|
* - With `React.FC`, the component implicitly accepts a `children` prop
|
|
* even if it's not defined in the prop type. This might not always be
|
|
* desirable, especially if the component doesn't intend to render
|
|
* children.
|
|
*/
|
|
const EmailField: React.FC<{
|
|
value: string;
|
|
}> = ({ value }) => <TextInput value={value} disabled fullWidth />;
|
|
```
|
|
|
|
```tsx
|
|
/* ✅ - Good, a separate type (OwnProps) is explicitly defined for the
|
|
* component's props
|
|
* - This method doesn't automatically include the children prop. If
|
|
* you want to include it, you have to specify it in OwnProps.
|
|
*/
|
|
type EmailFieldProps = {
|
|
value: string;
|
|
};
|
|
|
|
const EmailField = ({ value }: EmailFieldProps) => (
|
|
<TextInput value={value} disabled fullWidth />
|
|
);
|
|
```
|
|
|
|
#### No propagació de props d'una sola variable en elements JSX
|
|
|
|
Eviteu utilitzar la propagació de props d'una sola variable en elements JSX, com `{...props}`. Aquesta pràctica sovint resulta en un codi que és menys llegible i més difícil de mantenir perquè no està clar quines props està rebent el component.
|
|
|
|
```tsx
|
|
/* ❌ - Bad, spreads a single variable prop into the underlying component
|
|
*/
|
|
const MyComponent = (props: OwnProps) => {
|
|
return <OtherComponent {...props} />;
|
|
}
|
|
```
|
|
|
|
```tsx
|
|
/* ✅ - Good, Explicitly lists all props
|
|
* - Enhances readability and maintainability
|
|
*/
|
|
const MyComponent = ({ prop1, prop2, prop3 }: MyComponentProps) => {
|
|
return <OtherComponent {...{ prop1, prop2, prop3 }} />;
|
|
};
|
|
```
|
|
|
|
Racionalització:
|
|
|
|
- A primera vista, és més clar quines props es passen pel codi, fent-lo més fàcil d'entendre i de mantenir.
|
|
- Ajuda a evitar l'acoblament estricte entre els components a través de les seves props.
|
|
- Les eines de linteig faciliten identificar props mal escrites o no utilitzades quan es llisten explícitament les props.
|
|
|
|
## JavaScript
|
|
|
|
### Utilitzeu l'operador de coalescència nul·la `??`
|
|
|
|
```tsx
|
|
// ❌ Bad, can return 'default' even if value is 0 or ''
|
|
const value = process.env.MY_VALUE || 'default';
|
|
|
|
// ✅ Good, will return 'default' only if value is null or undefined
|
|
const value = process.env.MY_VALUE ?? 'default';
|
|
```
|
|
|
|
### Utilitzeu el cadenat opcional `?.`
|
|
|
|
```tsx
|
|
// ❌ Bad
|
|
onClick && onClick();
|
|
|
|
// ✅ Good
|
|
onClick?.();
|
|
```
|
|
|
|
## TypeScript
|
|
|
|
### Utilitzeu `type` en lloc de `interface`
|
|
|
|
Utilitzeu sempre `type` en lloc de `interface`, perquè gairebé sempre superposen, i `type` és més flexible.
|
|
|
|
```tsx
|
|
// ❌ Bad
|
|
interface MyInterface {
|
|
name: string;
|
|
}
|
|
|
|
// ✅ Good
|
|
type MyType = {
|
|
name: string;
|
|
};
|
|
```
|
|
|
|
### Utilitzeu literals de cadena en lloc d'enums
|
|
|
|
[Literals de cadena](https://www.typescriptlang.org/docs/handbook/2/everyday-types.html#literal-types) són el camí a seguir per manejar valors tipus enum a TypeScript. Són més fàcils d'ampliar amb Pick i Omit, i ofereixen una millor experiència per al desenvolupador, especialment amb l'autocompletar del codi.
|
|
|
|
Podeu veure per què TypeScript recomana evitar enums [aquí](https://www.typescriptlang.org/docs/handbook/2/everyday-types.html#enums).
|
|
|
|
```tsx
|
|
// ❌ Bad, utilizes an enum
|
|
enum Color {
|
|
Red = "red",
|
|
Green = "green",
|
|
Blue = "blue",
|
|
}
|
|
|
|
let color = Color.Red;
|
|
```
|
|
|
|
```tsx
|
|
// ✅ Good, utilizes a string literal
|
|
|
|
let color: "red" | "green" | "blue" = "red";
|
|
```
|
|
|
|
#### GraphQL i llibreries internes
|
|
|
|
Heu d'utilitzar enums que genera codegen de GraphQL.
|
|
|
|
També és millor utilitzar un enum quan s'utilitza una llibreria interna, de manera que la llibreria no hagi d'exposar un tipus de literal de cadena que no està relacionat amb la API interna.
|
|
|
|
Exemple:
|
|
|
|
```TSX
|
|
const {
|
|
setHotkeyScopeAndMemorizePreviousScope,
|
|
goBackToPreviousHotkeyScope,
|
|
} = usePreviousHotkeyScope();
|
|
|
|
setHotkeyScopeAndMemorizePreviousScope(
|
|
RelationPickerHotkeyScope.RelationPicker,
|
|
);
|
|
```
|
|
|
|
## Estilització
|
|
|
|
### Utilitzeu StyledComponents
|
|
|
|
Estilitzeu els components amb [styled-components](https://emotion.sh/docs/styled).
|
|
|
|
```tsx
|
|
// ❌ Bad
|
|
<div className="my-class">Hello World</div>
|
|
```
|
|
|
|
```tsx
|
|
// ✅ Good
|
|
const StyledTitle = styled.div`
|
|
color: red;
|
|
`;
|
|
```
|
|
|
|
Prefixeu els components estilitzats amb "Styled" per diferenciar-los dels components "reals".
|
|
|
|
```tsx
|
|
// ❌ Bad
|
|
const Title = styled.div`
|
|
color: red;
|
|
`;
|
|
```
|
|
|
|
```tsx
|
|
// ✅ Good
|
|
const StyledTitle = styled.div`
|
|
color: red;
|
|
`;
|
|
```
|
|
|
|
### Tematització
|
|
|
|
La utilització del tema per a la major part de l'estilització dels components és l'enfocament preferit.
|
|
|
|
#### Unitats de mesura
|
|
|
|
Eviteu utilitzar valors `px` o `rem` directament dins dels components estilitzats. Els valors necessaris generalment ja estan definits en el tema, així que és recomanable utilitzar el tema per a aquests propòsits.
|
|
|
|
#### Colors
|
|
|
|
Eviteu introduir nous colors; en comptes d'això, utilitzeu la paleta existent del tema. Si es presenta una situació on la paleta no s'alinea, si us plau, deixe un comentari perquè l'equip pugui rectificar-ho.
|
|
|
|
```tsx
|
|
// ❌ Bad, directly specifies style values without utilizing the theme
|
|
const StyledButton = styled.button`
|
|
color: #333333;
|
|
font-size: 1rem;
|
|
font-weight: 400;
|
|
margin-left: 4px;
|
|
border-radius: 50px;
|
|
`;
|
|
```
|
|
|
|
```tsx
|
|
// ✅ Good, utilizes the theme
|
|
const StyledButton = styled.button`
|
|
color: ${({ theme }) => theme.font.color.primary};
|
|
font-size: ${({ theme }) => theme.font.size.md};
|
|
font-weight: ${({ theme }) => theme.font.weight.regular};
|
|
margin-left: ${({ theme }) => theme.spacing(1)};
|
|
border-radius: ${({ theme }) => theme.border.rounded};
|
|
`;
|
|
```
|
|
|
|
## Aplicació de `No-Type Imports`
|
|
|
|
Eviteu les importacions de tipus. Per aplicar aquesta norma, una regla d'ESLint comprova i reporta qualsevol importació de tipus. Això ajuda a mantenir la consistència i la llegibilitat en el codi TypeScript.
|
|
|
|
```tsx
|
|
// ❌ Bad
|
|
import { type Meta, type StoryObj } from '@storybook/react';
|
|
|
|
// ❌ Bad
|
|
import type { Meta, StoryObj } from '@storybook/react';
|
|
|
|
// ✅ Good
|
|
import { Meta, StoryObj } from '@storybook/react';
|
|
```
|
|
|
|
### Per què `No-Type Imports`
|
|
|
|
- **Consistència**: Evitant les importacions de tipus i utilitzant un sol enfocament tant per a les importacions de tipus com per a les de valors, la base de codi es manté consistent en el seu estil de modul import.
|
|
|
|
- **Llegibilitat**: Les importacions sense tipus milloren la llegibilitat del codi al deixar clar quan s'estan important valors o tipus. Això redueix l'ambigüitat i facilita entendre el propòsit dels símbols importats.
|
|
|
|
- **Manteniment**: Millora la mantenibilitat de la base de codi perquè els desenvolupadors poden identificar i localitzar les importacions de tipus només quan revisen o modifiquen el codi.
|
|
|
|
### Regla d'ESLint
|
|
|
|
Una regla d'ESLint, `@typescript-eslint/consistent-type-imports`, aplica la norma de no importació de tipus. This rule will generate errors or warnings for any type import violations.
|
|
|
|
Si us plau, tingueu en compte que aquesta regla tracta específicament casos de límit rars on ocorren importacions de tipus no intencionades. El mateix TypeScript desaconsella aquesta pràctica, com es menciona a les [notes de llançament de TypeScript 3.8](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-8.html). En la majoria de situacions, no hauríeu de necessitar utilitzar importacions de tipus només.
|
|
|
|
Per assegurar-vos que el vostre codi compleixi amb aquesta regla, assegureu-vos de executar ESLint com a part del vostre flux de treball de desenvolupament.
|