--- title: Stil Rehberi icon: Boya fırçası description: Twenty'ye katkıda bulunmak için kod kuralları ve en iyi uygulamalar. --- ## React ### Yalnızca fonksiyonel bileşenler Her zaman named export'larla TSX fonksiyonel bileşenlerini kullanın. ```tsx // ❌ Bad const MyComponent = () => { return
Hello World
; }; export default MyComponent; // ✅ Good export function MyComponent() { return
Hello World
; }; ``` ### Özellikler `{ComponentName}Props` adında bir type oluşturun. Destructuring kullanın. `React.FC` kullanmayın. ```tsx type MyComponentProps = { name: string; }; export const MyComponent = ({ name }: MyComponentProps) =>
Hello {name}
; ``` ### Tek değişken için prop spread kullanmayın ```tsx // ❌ Bad const MyComponent = (props: MyComponentProps) => ; // ✅ Good const MyComponent = ({ prop1, prop2 }: MyComponentProps) => ; ``` ## Durum Yönetimi ### Global durum için Jotai atomları ```tsx import { createAtomState } from '@/ui/utilities/state/jotai/utils/createAtomState'; import { useAtomState } from '@/ui/utilities/state/jotai/hooks/useAtomState'; export const myAtomState = createAtomState({ key: 'myAtomState', defaultValue: 'default value', }); ``` * Prop drilling yerine atomları tercih edin * Durum için `useRef` kullanmayın — `useState` veya atomları kullanın * Listeler için atom ailelerini ve seçicileri kullanın ### Gereksiz yeniden render'ları önleyin * `useEffect` ve veri çekmeyi kardeş sidecar bileşenlere ayırın * `useEffect` yerine olay işleyicilerini (`handleClick`, `handleChange`) tercih edin * `React.memo()` kullanmayın — bunun yerine kök nedeni düzeltin * `useCallback` / `useMemo` kullanımını sınırlayın ```tsx // ❌ Bad — useEffect in the same component causes re-renders export const Page = () => { const [data, setData] = useAtomState(dataState); const [dep] = useAtomState(depState); useEffect(() => { setData(dep); }, [dep]); return
{data}
; }; // ✅ Good — extract into sibling export const PageData = () => { const [data, setData] = useAtomState(dataState); const [dep] = useAtomState(depState); useEffect(() => { setData(dep); }, [dep]); return <>; }; export const Page = () => { const [data] = useAtomState(dataState); return
{data}
; }; ``` ## TypeScript * **`interface` yerine `type`** — daha esnek, birleştirmesi daha kolay * **enum yerine string literal'lar** — GraphQL codegen enum'ları ve dahili kütüphane API'leri hariç * **`any` yok** — katı TypeScript zorunludur * **Type import'ları yok** — normal import'lar kullanın (Oxlint `typescript/consistent-type-imports` tarafından uygulanır) * **[Zod](https://github.com/colinhacks/zod) kullanın** tiplenmemiş nesnelerin çalışma zamanı doğrulaması için ## JavaScript ```tsx // Use nullish-coalescing (??) instead of || const value = process.env.MY_VALUE ?? 'default'; // Use optional chaining onClick?.(); ``` ## İsimlendirme * **Değişkenler**: camelCase, açıklayıcı (`email` değil `value`, `fieldMetadata` değil `fm`) * **Sabitler**: SCREAMING_SNAKE_CASE * **Tipler/Sınıflar**: PascalCase * **Dosyalar/dizinler**: kebab-case (`.component.tsx`, `.service.ts`, `.entity.ts`) * **Olay işleyicileri**: `handleClick` (işleyici fonksiyon için `onClick` değil) * **Bileşen prop'ları**: önek olarak bileşen adını kullanın (`ButtonProps`) * **Styled bileşenler**: `Styled` öneğini kullanın (`StyledTitle`) ## Stil [Linaria](https://github.com/callstack/linaria) ile stillendirilmiş bileşenleri kullanın. Tema değerlerini kullanın — kodda sabit tanımlanmış `px`, `rem` veya renklerden kaçının. ```tsx // ❌ Bad const StyledButton = styled.button` color: #333333; font-size: 1rem; margin-left: 4px; `; // ✅ Good const StyledButton = styled.button` color: ${({ theme }) => theme.font.color.primary}; font-size: ${({ theme }) => theme.font.size.md}; margin-left: ${({ theme }) => theme.spacing(1)}; `; ``` ## İçe Aktarımlar Göreli yollar yerine alias kullanın: ```tsx // ❌ Bad import { Foo } from '../../../../../testing/decorators/Foo'; // ✅ Good import { Foo } from '~/testing/decorators/Foo'; import { Bar } from '@/modules/bar/components/Bar'; ``` ## Klasör Yapısı ``` front └── modules/ # Feature modules │ └── module1/ │ ├── components/ │ ├── constants/ │ ├── contexts/ │ ├── graphql/ (fragments, queries, mutations) │ ├── hooks/ │ ├── states/ (atoms, selectors) │ ├── types/ │ └── utils/ └── pages/ # Route-level components └── ui/ # Reusable UI components (display, input, feedback, ...) ``` * Modüller diğer modüllerden import edebilir, ancak `ui/` bağımlılıksız kalmalıdır * `internal/` alt klasörlerini modüle özel kod için kullanın * Bileşenler 300 satırın altında, servisler 500 satırın altında