Dev Tips
Un trucchetto al giorno leva le complicazioni di torno! Piccole "scorciatoie" che possono facilitare la vita degli sviluppatori e far risparmiare tempo...e righe di codice.
Un trucchetto al giorno leva le complicazioni di torno! Piccole "scorciatoie" che possono facilitare la vita degli sviluppatori e far risparmiare tempo...e righe di codice.
2025-06-18
Contenuti dinamici visibili… anche senza JavaScript? Sì, si può! Attraverso il Server-Side Rendering (SSR) o Static Site Generation (SSG) e l'idratazione (con HydrationBoundary di TanStack Query), inviamo HTML completo con dati al browser. Se JavaScript è disattivato, l'utente (o il crawler) vedono il contenuto statico. Se attivo, TanStack Query "recupera" quei dati senza una nuova richiesta, offrendo un'esperienza dinamica e fluida. Un ottimo approccio per liste di prodotti, articoli, pagine con dati dinamici ma ad alta visibilità.
1//app/reactQueryProvider.tsx
2'use client';
3import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
4import React from 'react';
5
6export default function ReactQueryProvider({ children }: { children: React.ReactNode }) {
7// Istanza client-side di QueryClient (spesso globalizzata per persistenza)
8 const [queryClient] = React.useState(() => new QueryClient())
9
10 return (
11 <QueryClientProvider client={queryClient}>
12 {children}
13 </QueryClientProvider>
14 )
15}
16
17// app/layout.tsx (Configurazione del provider principale)
18import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
19import ReactQueryProvider from "./reactQueryProvider";
20
21export default function RootLayout({ children }: { children: React.ReactNode }) {
22 return (
23 <html lang="it">
24 <body>
25 <ReactQueryProvider>
26 {children} {/* HydrationBoundary sarà gestito nel componente pagina o un wrapper */}
27 </ReactQueryProvider>
28 </body>
29 </html>
30 );
31}
32
33// app/page.tsx (Componente Server-Side per Data Fetching e Rendering Iniziale)
34import { QueryClient, dehydrate, HydrationBoundary } from '@tanstack/react-query';
35import { MyClientList } from '../components/MyClientList';
36
37// Dati di esempio pre-caricati e renderizzati staticamente
38const serverFetchedData = [{ id: 1, name: 'Articolo A (Dal Server)' }];
39
40export default async function HomePage() {
41 // Crea una nuova istanza di QueryClient per ogni richiesta sul server
42 const queryClient = new QueryClient();
43
44 // Pre-fetch dei dati sul server (popola la cache di questa istanza di QueryClient)
45 await queryClient.prefetchQuery({
46 queryKey: ['articoli'],
47 queryFn: async () => {
48 console.log('SERVER: Prefetching per App Router...');
49 return serverFetchedData;
50 },
51 });
52
53 return (
54 <div>
55 {/* 1. Rendering statico per il fallback senza JS (incluso nell'HTML iniziale) */}
56 <h3>Contenuto Iniziale (HTML Server-Rendered)</h3>
57 <ul>
58 {serverFetchedData.map(item => (
59 <li key={item.id}>{item.name}</li>
60 ))}
61 </ul>
62
63 <hr />
64
65 {/* 2. Hydration Boundary: avvolge il componente client, passandogli lo stato */}
66 {/* `dehydrate(queryClient)` serializza la cache del server per il client */}
67 <HydrationBoundary state={dehydrate(queryClient)}>
68 <MyClientList /> {/* Questo componente userà useQuery, trovando i dati in cache */}
69 </HydrationBoundary>
70 </div>
71 );
72}
73
74// components/MyClientList.tsx (Il tuo Componente Client-Side che usa useQuery)
75'use client';
76import { useQuery } from '@tanstack/react-query';
77
78const fetchClientData = async () => {
79 console.log('CLIENT: Fetching (se non idratato)...');
80 return [{id: 101, name: 'Articolo X (Client)'}];
81};
82
83export function MyClientList() {
84 const { data } = useQuery({ queryKey: ['articoli'], queryFn: fetchClientData });
85 return (
86 <>
87 <h3>Contenuto Idratato (Client-Side)</h3>
88 <ul>{data?.map(item => <li key={item.id}>{item.name}</li>)}</ul>
89 </>
90 );
91}
2025-03-24
Il segreto di un software scalabile e manutenibile? Separare bene i livelli. Quando la logica di business è mescolata con la UI, il database e altre parti del sistema, tutto diventa confuso: le regole di business sono sparse ovunque, piccole modifiche rischiano di rompere il codice e il progetto diventa difficile da mantenere e scalare. Quando, invece, la logica di business è pulita e isolata, il codice diventa più chiaro e ogni cambiamento meno rischioso. Come questa pratica può salvare il tuo progetto?
1// Infrastructure Layer
2class DatabaseRepository {
3 save(entity: Entity): void { /* Persistence logic */ }
4}
5
6// Domain Layer
7class Order implements Entity {
8 private lineItems: OrderLine[];
9 // Other stuff...
10
11 isEligibleForDiscount(): boolean {
12 // Implementation code
13 }
14
15 applyDiscount(): void {
16 // Implementation code
17 }
18}
19
20// Application Layer
21class OrderService {
22 constructor(private repository: DatabaseRepository) {}
23
24 processOrder(order: Order): void {
25 if (order.isEligibleForDiscount()) {
26 order.applyDiscount();
27 }
28
29 this.repository.save(order);
30 }
31}
2025-02-25
Scrivere codice è facile ma scrivere codice che ha senso è tutta un’altra storia. Creare un buon modello non significa solo scrivere classi e metodi: è un processo di comprensione profonda del dominio che permette di tradurre concetti complessi in codice chiaro e manutenibile. Il Knowledge Crunching è proprio questo: un processo continuo di collaborazione tra sviluppatori ed esperti di dominio, che ci aiuta a perfezionare i modelli del business e a tradurre le complessità del mondo reale in soluzioni software robuste e scalabili. Ecco come dovrebbe essere un blocco di codice con il Knowledge Crunching:
1class Order {
2 private lineItems: OrderLine[] = [];
3 private total: Money;
4 private status = OrderStatus.DRAFT;
5
6 constructor() {
7 this.total = new Money(0, 'EUR');
8 }
9
10 addProduct(product: Product, quantity: Quantity): void {
11 if (this.status === OrderStatus.CONFIRMED) {
12 throw new OrderAlreadyConfirmedError();
13 }
14
15 const lineItem = new OrderLine(product, quantity);
16 this.lineItems = [...this.lineItems, lineItem];
17 this.recalculateTotal();
18 }
19
20 private recalculateTotal(): void {
21 this.total = this.lineItems.reduce(
22 (sum, item) => sum.add(item.calculateSubtotal()),
23 new Money(0, 'EUR')
24 );
25 }
26}
2024-10-23
1// users.mjs
2const res = await fetch('https://jsonplaceholder.typicode.com/users');
3const users = res.json();
4export { users };
5
6//module.mjs
7import {users} from './users.mjs';
8
9console.log(users);
2024-07-22
1// Using requestIdleCallback for scheduling low-priority background tasks
2const idleCallback = () => {
3 // Perform background tasks
4 console.log('Background task executed');
5};
6
7window.requestIdleCallback(idleCallback);
Hai in mente un progetto e vorresti realizzarlo?
Sei interessato a migliorare le competenze del tuo team in ambito di programmazione e sviluppo?
Oppure vuoi semplicemente prendere prendere un caffè con noi e vedere la nostra collezione di Action Figure, allora scrivici tramite questo form.
Se, invece, vuoi far parte del team, guarda le nostre offerte di lavoro.