Created by Github action --------- Co-authored-by: Crowdin Bot <support+bot@crowdin.com> Co-authored-by: github-actions <github-actions@twenty.com>
296 lines
11 KiB
Plaintext
296 lines
11 KiB
Plaintext
---
|
||
title: Водич за Стил
|
||
image: /images/user-guide/notes/notes_header.png
|
||
---
|
||
|
||
<Frame>
|
||
<img src="/images/user-guide/notes/notes_header.png" alt="Header" />
|
||
</Frame>
|
||
|
||
Овај документ укључује правила која треба следити приликом писања кода.
|
||
|
||
Циљ је да се обезбеди конзистентна база кода, која је лакша за читање и одржавање.
|
||
|
||
Због тога је боље бити мало обимнији него превише концизан.
|
||
|
||
Увек имајте на уму да се код чита чешће него што се пише, нарочито у пројектима отвореног кода, где свако може допринети.
|
||
|
||
Постоји много правила која овде нису дефинисана, али их аутоматски проверавају линтери.
|
||
|
||
## React
|
||
|
||
### Користите функционалне компоненте
|
||
|
||
Увек користите TSX функционалне компоненте.
|
||
|
||
Do not use default `import` with `const`, because it's harder to read and harder to import with code completion.
|
||
|
||
```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` ако не постоји потреба за експортовањем.
|
||
|
||
Користите деструктурирање пропсова.
|
||
|
||
```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>;
|
||
```
|
||
|
||
#### Избегавајте коришћење `React.FC` или `React.FunctionComponent` за дефинисање типова пропсова.
|
||
|
||
```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 Single Variable Prop Spreading in JSX Elements
|
||
|
||
Avoid using single variable prop spreading in JSX elements, like `{...props}`. Ова пракса често резултује кодом који је теже читати и одржавати јер није јасно који пропсови компонента прима.
|
||
|
||
```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 }} />;
|
||
};
|
||
```
|
||
|
||
Оправдање:
|
||
|
||
- На први поглед, јасније је које пропсове код прослеђује, што олакшава разумевање и одржавање.
|
||
- Помаже у спречавању блиског везивања компонената преко њихових пропсова.
|
||
- Алатке за проверу кода лакше идентификују погрешно написане или непотребне пропсове када експлицитно наводите пропсове.
|
||
|
||
## JavaScript
|
||
|
||
### Користите оператор нолицик-[coalescing](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Nullish_coalescing_operator) `??`
|
||
|
||
```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';
|
||
```
|
||
|
||
### Користите опционално повезивање `?.`
|
||
|
||
```tsx
|
||
// ❌ Bad
|
||
onClick && onClick();
|
||
|
||
// ✅ Good
|
||
onClick?.();
|
||
```
|
||
|
||
## TypeScript
|
||
|
||
### Користите `type` уместо `interface`
|
||
|
||
Увек користите `type` уместо `interface`, јер се скоро увек преклапају, а `type` је флексибилнији.
|
||
|
||
```tsx
|
||
// ❌ Bad
|
||
interface MyInterface {
|
||
name: string;
|
||
}
|
||
|
||
// ✅ Good
|
||
type MyType = {
|
||
name: string;
|
||
};
|
||
```
|
||
|
||
### Користите стринг литерале уместо енумс-а
|
||
|
||
[Стринг литерали](https://www.typescriptlang.org/docs/handbook/2/everyday-types.html#literal-types) су начин за рад са енум-сличним вредностима у TypeScript-у. Они су лакши за проширење са Pick и Omit и нуде боље корисничко искуство, нарочито са завршетком кода.
|
||
|
||
Можете видети зашто TypeScript препоручује избегавање енумс [овде](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 и интерне библиотеке
|
||
|
||
Требало би да користите енуме које генерише GraphQL код.
|
||
|
||
Такође је боље користити енум када се користи интерна библиотека, тако да интерна библиотека не мора да излаже тип стринг литерала који није повезан са интерним АПИ-јем.
|
||
|
||
Пример:
|
||
|
||
```TSX
|
||
const {
|
||
setHotkeyScopeAndMemorizePreviousScope,
|
||
goBackToPreviousHotkeyScope,
|
||
} = usePreviousHotkeyScope();
|
||
|
||
setHotkeyScopeAndMemorizePreviousScope(
|
||
RelationPickerHotkeyScope.RelationPicker,
|
||
);
|
||
```
|
||
|
||
## Стилизовање
|
||
|
||
### Use StyledComponents
|
||
|
||
Стилизујте компоненте са [styled-components](https://emotion.sh/docs/styled).
|
||
|
||
```tsx
|
||
// ❌ Bad
|
||
<div className="my-class">Hello World</div>
|
||
```
|
||
|
||
```tsx
|
||
// ✅ Good
|
||
const StyledTitle = styled.div`
|
||
color: red;
|
||
`;
|
||
```
|
||
|
||
Префиксирајте стилизоване компоненте са "Styled" да бисте их разликовали од "реалних" компоненти.
|
||
|
||
```tsx
|
||
// ❌ Bad
|
||
const Title = styled.div`
|
||
color: red;
|
||
`;
|
||
```
|
||
|
||
```tsx
|
||
// ✅ Good
|
||
const StyledTitle = styled.div`
|
||
color: red;
|
||
`;
|
||
```
|
||
|
||
### Тематизовање
|
||
|
||
Коришћење теме за већину стилизовања компоненти је пожељан приступ.
|
||
|
||
#### Јединице мере
|
||
|
||
Избегавајте коришћење `px` или `rem` вредности директно у стилизованим компонентама. Потребне вредности су генерално већ дефинисане у теми, па се препоручује коришћење теме у ове сврхе.
|
||
|
||
#### Боје
|
||
|
||
Избегавајте увођење нових боја; уместо тога, користите постојећу палету из теме. У случају да палета не одговара, оставите коментар како би тим могао да га исправи.
|
||
|
||
```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};
|
||
`;
|
||
```
|
||
|
||
## Спровођење Без-Типа Увоза
|
||
|
||
Избегавајте тип увоза. Да би се применио овај стандард, ESLint проверава и пријављује било који тип увоза. Ово одржава конзистентност и читљивост у 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';
|
||
```
|
||
|
||
### Зашто Без-Типа Увози
|
||
|
||
- **Конзистентност**: Избегавањем увоза типова и употребом истог приступа за увоз типова и вредности, база кода остаје конзистентна у стилу модула увоза.
|
||
|
||
- **Readability**: No-type imports improve code readability by making it clear when you're importing values or types. Ово смањује неодређеност и олакшава разумевање намене увезених симбола.
|
||
|
||
- **Одрживост**: Побољшава одрживост базе кода јер програмери могу да идентификују и пронађу увезене типове само када прегледавају или модификују код.
|
||
|
||
### Правило ESLint-а
|
||
|
||
An ESLint rule, `@typescript-eslint/consistent-type-imports`, enforces the no-type import standard. This rule will generate errors or warnings for any type import violations.
|
||
|
||
Please note that this rule specifically addresses rare edge cases where unintentional type imports occur. TypeScript сам обесхрабрује ову праксу, као што је наведено у [белешкама о издању за TypeScript 3.8](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-8.html). In most situations, you should not need to use type-only imports.
|
||
|
||
Да бисте осигурали да ваш код поштује ово правило, уверите се да покрећете ESLint као део вашег радног тока развоја.
|