RN Lezione 3: Componenti, JSX e Props
Obiettivi
Section titled “Obiettivi”- Capire il paradigma a componenti di React
- Scrivere JSX correttamente
- Usare props per passare dati tra componenti
- Comporre componenti insieme
1. Il paradigma a componenti
Section titled “1. Il paradigma a componenti”In React, tutto è un componente. Un componente è una funzione che ritorna JSX (markup).
// Componente sempliceconst Saluto = () => { return <Text>Ciao!</Text>;};
// Uso nel componente genitore<Saluto />Perché i componenti?
Section titled “Perché i componenti?”| Vantaggio | Spiegazione |
|---|---|
| Riutilizzo | Scrivi una volta, usi ovunque |
| Separazione | Ogni pezzo UI è indipendente |
| Testabilità | Testi ogni componente da solo |
| Leggibilità | Codice più facile da leggere e mantenere |
Regole dei componenti
Section titled “Regole dei componenti”- Nome in maiuscolo:
Card✅,card❌ - Una funzione che ritorna JSX
- Si usa come tag HTML:
<Card />
// ✅ Correttoconst Card = () => { return <Text>Ciao</Text>;};
// ❌ SBAGLIATO — nome minuscoloconst card = () => { return <Text>Ciao</Text>;};2. JSX — JavaScript XML
Section titled “2. JSX — JavaScript XML”JSX è un’estensione di JavaScript che sembra HTML ma è JavaScript.
Regole JSX
Section titled “Regole JSX”- Un solo elemento radice — tutto dentro un
<View>o<></> {}per inserire JavaScript nel markupstyle={}prende un oggetto, non una stringa- I commenti JSX:
{/* commento */}
// ✅ Corretto — un solo View radicereturn ( <View> <Text>Ciao</Text> <Text>Mondo</Text> </View>);
// ✅ Corretto — Fragment (<> = View senza stili)return ( <> <Text>Ciao</Text> <Text>Mondo</Text> </>);
// ❌ SBAGLIATO — due elementi radicereturn ( <Text>Ciao</Text> <Text>Mondo</Text>);Espressioni in JSX
Section titled “Espressioni in JSX”const nome = 'Mario';
return ( <View> <Text>Ciao, {nome}!</Text> <Text>{2 + 2}</Text> <Text>{nome.toUpperCase()}</Text> <Text>{nome.length > 3 ? 'Lungo' : 'Corto'}</Text> {/* ↑ operatore ternario = if inline */} </View>);3. Props — passare dati ai componenti
Section titled “3. Props — passare dati ai componenti”Le props sono come parametri di funzione per i componenti.
// Definizione del componente Cardconst Card = (props) => { return ( <View style={styles.card}> <Text style={styles.titolo}>{props.titolo}</Text> <Text style={styles.descrizione}>{props.descrizione}</Text> </View> );};
// Uso — passo dati come attributi<Card titolo="Python" descrizione="Linguaggio di programmazione"/><Card titolo="JavaScript" descrizione="Il linguaggio del web"/>Destrutturazione delle props (metodo preferito)
Section titled “Destrutturazione delle props (metodo preferito)”// ✅ Preferito — destrutturazione nei parametriconst Card = ({ titolo, descrizione, autore = 'Anonimo' }) => { // ↑ default se non passato return ( <View style={styles.card}> <Text style={styles.titolo}>{titolo}</Text> <Text>{descrizione}</Text> <Text>Autore: {autore}</Text> </View> );};Le props sono read-only
Section titled “Le props sono read-only”⚠️ Non modificare mai le props! Sono come parametri di funzione:
// ❌ SBAGLIATO — non modificare le propsconst Card = ({ titolo }) => { titolo = 'Nuovo titolo'; // ERRORE! return <Text>{titolo}</Text>;};4. Composizione — componenti dentro componenti
Section titled “4. Composizione — componenti dentro componenti”// Componente piccolo: Avatarconst Avatar = ({ nome, colore }) => { return ( <View style={[styles.cerchio, { backgroundColor: colore }]}> <Text style={styles.iniziale}>{nome[0]}</Text> </View> );};
// Componente medio: CardProfilo (USA Avatar dentro)const CardProfilo = ({ nome, bio, colore }) => { return ( <View style={styles.card}> <Avatar nome={nome} colore={colore} /> <View style={styles.info}> <Text style={styles.nome}>{nome}</Text> <Text style={styles.bio}>{bio}</Text> </View> </View> );};
// Componente principale: App (USA CardProfilo dentro)export default function App() { return ( <View style={styles.container}> <CardProfilo nome="Mario" bio="Studente 4A" colore="blue" /> <CardProfilo nome="Sofia" bio="Studente 4B" colore="red" /> <CardProfilo nome="Luca" bio="Studente 4A" colore="green" /> </View> );}5. children — contenuto annidato
Section titled “5. children — contenuto annidato”La prop speciale children contiene tutto ciò che è tra i tag di apertura e chiusura.
// Contenitore genericoconst Card = ({ children, style }) => { return ( <View style={[styles.card, style]}> {children} {/* ← tutto ciò che sta dentro <Card>...</Card> */} </View> );};
// Uso<Card style={{ backgroundColor: '#e3f2fd' }}> <Text>Questo è dentro la card</Text> <Text>Anche questo</Text></Card>Pattern: layout con header, content, footer
Section titled “Pattern: layout con header, content, footer”const Pagina = ({ header, children, footer }) => { return ( <View style={{ flex: 1 }}> <View style={styles.header}>{header}</View> <View style={styles.content}>{children}</View> <View style={styles.footer}>{footer}</View> </View> );};
// Uso<Pagina header={<Text style={styles.titolo}>Home</Text>} footer={<Text>© 2026</Text>}> <Text>Contenuto della pagina</Text> <Text>Altro contenuto</Text></Pagina>6. Esempio guidato: Schermata profilo composta
Section titled “6. Esempio guidato: Schermata profilo composta”import { View, Text, StyleSheet } from 'react-native';
// --- Sotto-componenti ---const Avatar = ({ nome, colore }) => ( <View style={[styles.avatar, { backgroundColor: colore }]}> <Text style={styles.iniziale}>{nome[0]}</Text> </View>);
const Badge = ({ testo, colore }) => ( <View style={[styles.badge, { backgroundColor: colore + '20' }]}> <Text style={[styles.badgeTesto, { color: colore }]}>{testo}</Text> </View>);
const InfoRiga = ({ label, valore }) => ( <View style={styles.riga}> <Text style={styles.label}>{label}</Text> <Text style={styles.valore}>{valore}</Text> </View>);
// --- Componente principale ---export default function App() { return ( <View style={styles.container}> <View style={styles.card}> <Avatar nome="Mario" colore="#3498db" /> <Text style={styles.nome}>Mario Rossi</Text> <Text style styles={styles.ruolo}>Studente 4A Informatica</Text>
<View style={styles.badgeRow}> <Badge testo="Python" colore="#2ecc71" /> <Badge testo="React" colore="#3498db" /> <Badge testo="Flet" colore="#9b59b6" /> </View>
<View style={styles.separatore} />
<InfoRiga label="Età" valore="17" /> <InfoRiga label="Scuola" valore="ITI Fermi" /> <InfoRiga label="Media" valore="8.5" /> </View> </View> );}
const styles = StyleSheet.create({ container: { flex: 1, justifyContent: 'center', alignItems: 'center', backgroundColor: '#f0f4f8', }, card: { backgroundColor: 'white', padding: 30, borderRadius: 20, alignItems: 'center', width: '85%', elevation: 5, shadowColor: '#000', shadowOpacity: 0.1, shadowRadius: 10, }, avatar: { width: 80, height: 80, borderRadius: 40, justifyContent: 'center', alignItems: 'center', marginBottom: 15, }, iniziale: { fontSize: 32, fontWeight: 'bold', color: 'white', }, nome: { fontSize: 22, fontWeight: 'bold', }, ruolo: { fontSize: 14, color: 'grey', marginBottom: 15, }, badgeRow: { flexDirection: 'row', gap: 8, marginBottom: 15, }, badge: { paddingHorizontal: 12, paddingVertical: 4, borderRadius: 12, }, badgeTesto: { fontSize: 12, fontWeight: '600', }, separatore: { width: '100%', height: 1, backgroundColor: '#eee', marginBottom: 15, }, riga: { flexDirection: 'row', justifyContent: 'space-between', width: '100%', marginBottom: 8, }, label: { color: 'grey', }, valore: { fontWeight: '600', },});Nota: c’è un errore voluto nel codice sopra (
style stylesnella riga del ruolo). Trovalo e correggilo! 🐛
7. Tabella riassuntiva
Section titled “7. Tabella riassuntiva”| Concetto | Sintassi |
|---|---|
| Componente | const Card = () => { return <View>...</View>; } |
| Props | const Card = ({ titolo, ... }) => { ... } |
| Default props | const Card = ({ titolo = 'Default' }) => { ... } |
| Children | {children} tra i tag |
| Fragment | <> ... </> |
| JSX JS | {variabile} o {funzione()} |
8. Esercizio autonomo
Section titled “8. Esercizio autonomo”🎯 Esercizio: “Galleria di Card”
Section titled “🎯 Esercizio: “Galleria di Card””Crea una schermata con:
- Componente
Prodottoche accetta props:nome,prezzo,colore - Mostra nome (grande, grassetto) e prezzo (verde, con €)
- Un badge con la prima lettera del nome come sfondo colorato
- Usa la card dentro App con almeno 4 prodotti diversi
Requisiti
Section titled “Requisiti”- Tutti gli stili in
StyleSheet.create() - Props destrutturate
- Default per il colore (
'#ccc') flexWrap: 'wrap'per disporre le card su più righe