--- title: Osvedčené postupy image: /images/user-guide/tips/light-bulb.png --- Header Tento dokument popisuje osvědčené postupy, které byste měli dodržovat při práci na frontend. ## Správa stavu React a Recoil zajišťují správu stavu v kódu. ### Použijte `useRecoilState` k ukládání stavu Je dobrým zvykem vytvořit tolik atomů, kolik potřebujete ke správě stavu. Je lepší použít více atomů než se snažit být příliš stručný s prop drilling. ```tsx export const myAtomState = atom({ key: 'myAtomState', default: 'default value', }); export const MyComponent = () => { const [myAtom, setMyAtom] = useRecoilState(myAtomState); return (
setMyAtom(e.target.value)} />
); } ``` ### Nepoužívejte `useRef` k ukládání stavu Vyhněte se používání `useRef` k ukládání stavu. Pokud chcete ukládat stav, měli byste použít `useState` nebo `useRecoilState`. Podívejte se, jak spravovat překreslení, pokud máte pocit, že potřebujete `useRef`, abyste zabránili některým překreslením. ## Správa překreslení Překreslení může být obtížné spravovat v Reactu. Zde jsou některá pravidla, která je třeba dodržovat, abyste se vyhnuli zbytečnému překreslování. Pamatujte, že můžete **vždy** zabránit opakovanému renderování pochopením jejich příčiny. ### Pracujte na úrovni kořene Vyhýbání se překreslení v nových funkcích je nyní snadné tím, že je eliminujete na úrovni kořene. Komponenta sidecar `PageChangeEffect` obsahuje pouze jedno `useEffect`, kde drží veškerou logiku vykonávanou při změně stránky. Tímto způsobem víte, že existuje pouze jedno místo, které může spustit překreslování. ### Vždy přemýšlejte dvakrát, než přidáte `useEffect` do svého kódu Překreslování je často způsobeno zbytečným `useEffect`. Měli byste přemýšlet, zda potřebujete `useEffect`, nebo jestli můžete logiku přesunout do funkce obsluhy událostí. Obecně budete snadno moci přesunout logiku do funkce `handleClick` nebo `handleChange`. Můžete je také najít v knihovnách jako Apollo: `onCompleted`, `onError` atd. ### Použijte sourozenou komponentu k extrakci logiky `useEffect` nebo získávání dat Pokud máte pocit, že potřebujete přidat `useEffect` do svého základního komponentu, měli byste zvážit jeho extrakci do sidecar komponenty. Stejný postup můžete aplikovat na logiku získávání dat pomocí 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
{data}
; }; export const App = () => ( ); ``` ```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
{data}
; }; export const PageData = () => { const [data, setData] = useRecoilState(dataState); const [someDependency] = useRecoilState(someDependencyState); useEffect(() => { if(someDependency !== data) { setData(someDependency); } }, [someDependency]); return <>; }; export const App = () => ( ); ``` ### Použijte Recoil family states a Recoil family selectors Stavy rodiny třísek a selektory jsou skvělý způsob, jak se vyhnout překreslování. Jsou užitečné, když potřebujete uložit seznam položek. ### Neměli byste používat `React.memo(MyComponent)` Vyhněte se používání `React.memo()`, protože to neřeší příčinu překreslování, ale spíše přeruší řetězec překreslování, což může vést k neočekávanému chování a ztěžuje refaktorování kódu. ### Omezit použití `useCallback` nebo `useMemo` Často nejsou nutné a kód ztěžují na čtení a údržbu pro nepodstatné zlepšení výkonu. ## Console.logs Příkazy `console.log` jsou hodnotné při vývoji, protože poskytují pohled na hodnoty proměnných a průběh kódu v reálném čase. Ale, zanechání v produkčním kódu může vést k několika problémům: 1. **Výkon**: Přílišné logování může ovlivnit výkon za běhu, zejména u aplikací na straně klienta. 2. **Bezpečnost**: Logování citlivých dat může vystavit kritické informace komukoliv, kdo nahlédne do konzole prohlížeče. 3. **Čistota**: Naplnění konzole logy může zatížit důležitá varování nebo chyby, které je třeba vidět. 4. **Profesionalita**: Koneční uživatelé nebo klienti kontrolující konzolu a vidící množství logovacích příkazů mohou zpochybnit kvalitu a úroveň kódu. Ujistěte se, že odstraníte všechny `console.logs`, než uvedete kód do produkce. ## Pojmenovávání ### Pojmenování proměnných Jména proměnných by měla přesně zobrazovat účel nebo funkci proměnné. #### Problém s generickými jmény Generická jména v programování nejsou ideální, protože postrádají specifikaci, což vede k nejednoznačnosti a snižuje čitelnost kódu. Taková jména neposkytnou informace o účelu proměnné nebo funkce, čímž ztěžují vývojářům pochopení záměru kódu bez hlubšího zkoumání. To může vést ke zvýšené době ladění, vyšší náchylnosti k chybám a obtížím při údržbě a spolupráci. Mezitím, použití popisných jmen činí kód samozřejmým a snadněji navigovatelným, čímž se zvyšuje jeho kvalita a produktivita vývojáře. ```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ěkterá slova, kterým se vyhnout v názvech proměnných - dummy ### Obsluhovače událostí Jména obsluhovačů událostí by měla začínat `handle`, zatímco `on` je prefix používaný k pojmenování událostí v komponentech props. ```tsx // ❌ Bad const onEmailChange = (val: string) => { // ... }; ``` ```tsx // ✅ Good const handleEmailChange = (val: string) => { // ... }; ``` ## Volitelné props Vyhněte se tomu, abyste pro volitelný props předávali výchozí hodnotu. **PŘÍKLAD** Vezměte komponent `EmailField` definovanou níže: ```tsx type EmailFieldProps = { value: string; disabled?: boolean; }; const EmailField = ({ value, disabled = false }: EmailFieldProps) => ( ); ``` **Použití** ```tsx // ❌ Bad, passing in the same value as the default value adds no value const Form = () => ; ``` ```tsx // ✅ Good, assumes the default value const Form = () => ; ``` ## Komponenta jako props Pokuste se co nejvíce předávat neinstancované komponenty jako props, aby si děti mohly samy rozhodnout, které props potřebují předat. Nejčastější příklad je komponenta ikon: ```tsx const SomeParentComponent = () => ; // In MyComponent const MyComponent = ({ MyIcon }: { MyIcon: IconComponent }) => { const theme = useTheme(); return (
) }; ``` Aby React pochopil, že komponenta je komponenta, musíte použít PascalCase, aby později ji bylo možné instancovat pomocí `` ## Prop Drilling: Udržujte to minimální Prop drilling, v kontextu React, odkazuje na praktiku předávání stavových proměnných a jejich setterů skrze mnoho vrstev komponent, i když mezilehlé komponenty je nepoužívají. Zatímco občas je to nutné, přehnané prop drilling může vést k: 1. **Snížená čitelnost**: Sledování původu nebo využití vlastnosti může být komplikované ve složitě vnořených strukturách komponent. 2. **Problémy s údržbou**: Změny v struktuře vlastností jedné komponenty mohou vyžadovat úpravy v některých komponentech, i když tyto vlastnosti přímo nepoužívají. 3. **Snížená znovupoužitelnost komponentů**: Komponent přijímající mnoho props pouze pro jejich předání, se stává méně univerzálním a obtížněji použitelným v různých kontextech. Pokud máte pocit, že používáte přílišné prop drilling, podívejte se na osvědčené postupy správy stavu. ## Importy Při importu, upřednostněte určené aliasy před upřesňováním úplných či relativních cest. **Aliasy** ```js { alias: { "~": path.resolve(__dirname, "src"), "@": path.resolve(__dirname, "src/modules"), "@testing": path.resolve(__dirname, "src/testing"), }, } ``` **Použití** ```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'; ``` ## Validace schématu [Zod](https://github.com/colinhacks/zod) je validátor schémat pro netypová data: ```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; ``` ## Zlomové změny Vždy proveďte důkladné manuální testování, abyste zajistili, že úpravy nezpůsobily problémy jinde, zejména pokud testy zatím nebyly široce integrovány.