--- title: Migliori Pratiche icon: star --- Questo documento descrive le migliori pratiche da seguire quando si lavora sul frontend. ## Gestione dello Stato React e Jotai gestiscono lo stato nella base di codice. ### Usa gli atomi di Jotai per memorizzare lo stato È buona pratica creare tanti atomi quanti servono per memorizzare il tuo stato. È meglio usare atomi extra piuttosto che cercare di essere troppo concisi con l'iniezione di props. ```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', }); export const MyComponent = () => { const [myAtom, setMyAtom] = useAtomState(myAtomState); return (
setMyAtom(e.target.value)} />
); } ``` ### Non utilizzare `useRef` per memorizzare lo stato Evita di usare `useRef` per memorizzare lo stato. Se vuoi memorizzare lo stato, dovresti usare `useState` o gli atomi di Jotai con `useAtomState`. Consulta [come gestire i re-render](#managing-re-renders) se senti che hai bisogno di `useRef` per evitare alcuni re-render. ## Gestione dei Re-Render I re-render possono essere difficili da gestire in React. Ecco alcune regole da seguire per evitare re-render non necessari. Tieni presente che puoi **sempre** evitare i re-render comprendendo la loro causa. ### Lavora a livello radice Evitare i re-render in nuove funzionalità è ora più semplice eliminandoli a livello radice. Il componente sidecar `PageChangeEffect` contiene un solo `useEffect` che detiene tutta la logica da eseguire su un cambio di pagina. In questo modo sai che c'è solo un luogo che può attivare un re-render. ### Pensa sempre due volte prima di aggiungere `useEffect` nel tuo codice I re-render sono spesso causati da `useEffect` non necessari. Dovresti pensare se hai bisogno di `useEffect`, o se puoi spostare la logica in una funzione gestore di eventi. Troverai generalmente facile spostare la logica in una funzione `handleClick` o `handleChange`. Puoi trovarli anche in librerie come Apollo: `onCompleted`, `onError`, ecc. ### Usa un componente simile per estrarre la logica `useEffect` o di recupero dati Se senti di dover aggiungere un `useEffect` nel tuo componente radice, dovresti considerare di estrarlo in un componente sidecar. Puoi applicare lo stesso per la logica di recupero dati, con i hook di Apollo. ```tsx // ❌ Sconsigliato, causerà re-render anche se i dati non cambiano, // perché useEffect deve essere ri-eseguito export const PageComponent = () => { const [data, setData] = useAtomState(dataState); const [someDependency] = useAtomState(someDependencyState); useEffect(() => { if(someDependency !== data) { setData(someDependency); } }, [someDependency]); return
{data}
; }; export const App = () => ( ); ``` ```tsx // ✅ Consigliato, non causerà re-render se i dati non cambiano, // perché useEffect viene ri-eseguito in un altro componente fratello export const PageComponent = () => { const [data, setData] = useAtomState(dataState); return
{data}
; }; export const PageData = () => { const [data, setData] = useAtomState(dataState); const [someDependency] = useAtomState(someDependencyState); useEffect(() => { if(someDependency !== data) { setData(someDependency); } }, [someDependency]); return <>; }; export const App = () => ( <> ); ``` ### Usa gli stati e i selettori della famiglia di atomi Gli stati e i selettori della famiglia di atomi sono un ottimo modo per evitare re-render. Sono utili quando hai bisogno di memorizzare una lista di elementi. ### Non dovresti usare `React.memo(MyComponent)` Evita di usare `React.memo()` perché non risolve la causa del re-render, ma interrompe invece la catena di re-render, il che può portare a comportamenti inaspettati e rendere il codice molto difficile da rifattorizzare. ### Limita l'uso di `useCallback` o `useMemo` Spesso non sono necessari e renderanno il codice più difficile da leggere e mantenere per un guadagno di prestazioni che è impercettibile. ## Console.log Le dichiarazioni `console.log` sono preziose durante lo sviluppo, offrendo informazioni in tempo reale sui valori delle variabili e sul flusso del codice. Tuttavia, lasciarli nel codice di produzione può causare diversi problemi: 1. **Prestazioni**: Un logging eccessivo può influire sulle prestazioni di runtime, soprattutto nelle applicazioni lato client. 2. **Sicurezza**: Registrare dati sensibili può esporre informazioni critiche a chiunque ispezioni la console del browser. 3. **Pulizia**: Riempire la console di log può oscurare avvertimenti o errori importanti che sviluppatori o strumenti devono vedere. 4. **Professionalità**: Gli utenti finali o i clienti che controllano la console e vedono una miriade di dichiarazioni di log potrebbero mettere in dubbio la qualità e la raffinatezza del codice. Assicurati di rimuovere tutti i `console.logs` prima di distribuire il codice in produzione. ## Denominazione ### Denominazione delle Variabili I nomi delle variabili dovrebbero descrivere precisamente lo scopo o la funzione della variabile. #### Il problema con i nomi generici I nomi generici nella programmazione non sono ideali perché mancano di specificità, portando all'ambiguità e riducendo la leggibilità del codice. Tali nomi non riescono a trasmettere lo scopo della variabile o della funzione, rendendo difficile per gli sviluppatori comprendere l'intento del codice senza un'indagine più approfondita. Questo può risultare in tempi di debug più lunghi, maggiore suscettibilità agli errori e difficoltà nella manutenzione e nella collaborazione. Nel frattempo, una denominazione descrittiva rende il codice autoesplicativo e più facile da navigare, migliorando la qualità del codice e la produttività dello sviluppatore. ```tsx // ❌ Sconsigliato, usa un nome generico che non comunica chiaramente // scopo o contenuto const [value, setValue] = useState(''); ``` ```tsx // ✅ Consigliato, usa un nome descrittivo const [email, setEmail] = useState(''); ``` #### Alcune parole da evitare nei nomi delle variabili * fittizio ### Gestori di Eventi I nomi dei gestori degli eventi dovrebbero iniziare con `handle`, mentre `on` è un prefisso usato per nominare gli eventi nelle props dei componenti. ```tsx // ❌ Sconsigliato const onEmailChange = (val: string) => { // ... }; ``` ```tsx // ✅ Consigliato const handleEmailChange = (val: string) => { // ... }; ``` ## Props Opzionali Evita di passare il valore predefinito per una prop opzionale. **ESEMPIO** Guarda il componente `EmailField` definito di seguito: ```tsx type EmailFieldProps = { value: string; disabled?: boolean; }; const EmailField = ({ value, disabled = false }: EmailFieldProps) => ( ); ``` **Utilizzo** ```tsx // ❌ Sconsigliato, passare lo stesso valore del valore predefinito non apporta alcun beneficio const Form = () => ; ``` ```tsx // ✅ Consigliato, presume il valore predefinito const Form = () => ; ``` ## Componente come props Cercate, per quanto possibile, di passare componenti non istanziati come props, così i figli possono decidere autonomamente quali props devono passare. L'esempio più comune per questo sono i componenti icona: ```tsx const SomeParentComponent = () => ; // Nel componente MyComponent const MyComponent = ({ MyIcon }: { MyIcon: IconComponent }) => { const theme = useTheme(); return (
) }; ``` Per far sì che React capisca che il componente è un componente, è necessario usare PascalCase, per poi istanziarlo con ``. ## Prop Drilling: Mantienilo Minimal Il prop drilling, nel contesto di React, si riferisce alla pratica di passare variabili di stato e i loro setter attraverso molti livelli di componenti, anche se i componenti intermedi non li usano. Anche se a volte è necessario, un eccessivo prop drilling può portare a: 1. **Diminuzione della leggibilità**: Tracciare da dove proviene un prop o dove viene utilizzato può diventare complicato in una struttura di componenti profondamente nidificata. 2. **Sfide di manutenzione**: Cambiamenti nella struttura dei props di un componente potrebbero richiedere aggiustamenti in diversi componenti, anche se non utilizzano direttamente il prop. 3. **Ridotta riutilizzabilità del componente**: Un componente che riceve molti props solo per passarli diventa meno generico e più difficile da riutilizzare in contesti diversi. Se ritieni di utilizzare eccessivo prop drilling, vedi [migliori pratiche di gestione dello stato](#state-management). ## Importa Quando importi, opta per gli alias designati anziché specificare percorsi completi o relativi. **Gli alias** ```js { alias: { "~": path.resolve(__dirname, "src"), "@": path.resolve(__dirname, "src/modules"), "@testing": path.resolve(__dirname, "src/testing"), }, } ``` **Utilizzo** ```tsx // ❌ Sconsigliato, specifica l'intero percorso relativo import { CatalogDecorator } from '../../../../../testing/decorators/CatalogDecorator'; import { ComponentDecorator } from '../../../../../testing/decorators/ComponentDecorator'; ``` ```tsx // ✅ Consigliato, utilizza gli alias designati import { CatalogDecorator } from '~/testing/decorators/CatalogDecorator'; import { ComponentDecorator } from 'twenty-ui/testing'; ``` ## Validazione dello Schema [Zod](https://github.com/colinhacks/zod) è il validatore di schema per oggetti non tipizzati: ```js const validationSchema = z .object({ exist: z.boolean(), email: z .string() .email('L\'indirizzo email deve essere valido'), password: z .string() .regex(PASSWORD_REGEX, 'La password deve contenere almeno 8 caratteri'), }) .required(); type Form = z.infer; ``` ## Modifiche Incompatibili Esegui sempre test manuali approfonditi prima di procedere per garantire che le modifiche non abbiano causato interruzioni altrove, dato che i test non sono ancora stati ampiamente integrati.