RN Lezione 4: useState, Eventi e TextInput
Obiettivi
Section titled “Obiettivi”- Gestire lo stato locale con
useState - Catturare eventi (onPress, onChangeText)
- Usare TextInput e Button
- Costruire form interattivi
1. useState — lo stato del componente
Section titled “1. useState — lo stato del componente”useState permette a un componente di ricordare dati che cambiano.
import { useState } from 'react'; // ← importa useState
const Contatore = () => { const [count, setCount] = useState(0); // ↑ ↑ ↑ // valore funzione che valore iniziale // lo aggiorna
const incrementa = () => { setCount(count + 1); // ← aggiorna il valore };
return ( <View> <Text>Hai cliccato {count} volte</Text> <Button title="+1" onPress={incrementa} /> </View> );};Come funziona?
Section titled “Come funziona?”useState(0)→ crea una variabilecountinizializzata a 0setCount(nuovoValore)→ aggiorna il valore- Quando
setCountviene chiamato, il componente si ri-renderizza (si aggiorna la UI)
// Schema mentale:// cost [valore, setValore] = useState(iniziale)// ↑ ↑ ↑// LEGGERE SCRIVERE PRIMA VOLTARegole importanti
Section titled “Regole importanti”// ✅ Correttoconst [nome, setNome] = useState('Mario');
// ❌ Non modificare direttamente!nome = 'Luigi'; // NON funziona — la UI non si aggiornasetNome('Luigi'); // ✅ Corretto — la UI si aggiorna2. Button e onPress
Section titled “2. Button e onPress”import { Button } from 'react-native';
<Button title="Cliccami" // Testo del bottone onPress={funzione} // Funzione da chiamare al click color="blue" // Colore (solo Android) disabled={false} // Disabilitato?/>Tre modi di scrivere l’handler
Section titled “Tre modi di scrivere l’handler”// 1. Funzione esterna (più leggibile)const incrementa = () => { setCount(count + 1);};<Button title="+1" onPress={incrementa} />
// 2. Arrow function inline (semplice)<Button title="+1" onPress={() => setCount(count + 1)} />
// 3. NO: chiamata diretta (si esegue SUBITO!)<Button title="+1" onPress={setCount(count + 1)} /> // ❌ ERRORE!3. Esempio: Contatore completo
Section titled “3. Esempio: Contatore completo”import { View, Text, Button, StyleSheet } from 'react-native';import { useState } from 'react';
export default function App() { const [count, setCount] = useState(0);
return ( <View style={styles.container}> <Text style={styles.numero}>{count}</Text> <View style={styles.riga}> <Button title="-1" onPress={() => setCount(count - 1)} color="red" /> <Button title="Reset" onPress={() => setCount(0)} /> <Button title="+1" onPress={() => setCount(count + 1)} color="green" /> </View> </View> );}
const styles = StyleSheet.create({ container: { flex: 1, justifyContent: 'center', alignItems: 'center', backgroundColor: '#f5f5f5', }, numero: { fontSize: 60, fontWeight: 'bold', marginBottom: 30, color: count < 0 ? 'red' : count > 10 ? 'green' : 'black', }, riga: { flexDirection: 'row', gap: 10, },});Nota:
countnella style è calcolato inline — cambia colore in base al valore! 🎨
4. TextInput — campi di input
Section titled “4. TextInput — campi di input”import { TextInput } from 'react-native';import { useState } from 'react';
const FormNome = () => { const [nome, setNome] = useState('');
return ( <View> <TextInput style={styles.input} placeholder="Il tuo nome" value={nome} // ← valore controllato onChangeText={setNome} // ← equivalente a (text) => setNome(text) /> <Text>Ciao, {nome}!</Text> </View> );};
const styles = StyleSheet.create({ input: { borderWidth: 1, borderColor: '#ccc', padding: 12, borderRadius: 8, fontSize: 16, marginBottom: 10, },});Proprietà principali di TextInput
Section titled “Proprietà principali di TextInput”| Proprietà | Descrizione | Esempio |
|---|---|---|
value | Valore controllato | value={nome} |
onChangeText | Chiamata quando cambia | onChangeText={setNome} |
placeholder | Testo di suggerimento | placeholder="Nome..." |
secureTextEntry | Per password | secureTextEntry={true} |
multiline | Multi riga (textarea) | multiline={true} |
keyboardType | Tipo tastiera | keyboardType="numeric" |
maxLength | Massimo caratteri | maxLength={20} |
editable | Disabilita input? | editable={false} |
Tipi di keyboardType
Section titled “Tipi di keyboardType”keyboardType="default" // Testo normalekeyboardType="numeric" // Solo numerikeyboardType="email-address" // Email (@)keyboardType="phone-pad" // TelefonokeyboardType="decimal-pad" // Numeri con virgola5. Esempio guidato: Form presentazione
Section titled “5. Esempio guidato: Form presentazione”import { View, Text, TextInput, Button, StyleSheet, Alert } from 'react-native';import { useState } from 'react';
export default function App() { const [nome, setNome] = useState(''); const [eta, setEta] = useState(''); const [inviato, setInviato] = useState(false);
const invia = () => { if (!nome || !eta) { Alert.alert('Errore', 'Compila tutti i campi!'); return; } setInviato(true); };
const reset = () => { setNome(''); setEta(''); setInviato(false); };
if (inviato) { return ( <View style={styles.container}> <Text style={styles.titolo}>✅ Dati ricevuti!</Text> <Text style={styles.dato}>Nome: {nome}</Text> <Text style={styles.dato}>Età: {eta}</Text> <Button title="Torna indietro" onPress={reset} /> </View> ); }
return ( <View style={styles.container}> <Text style={styles.titolo}>Chi sei?</Text> <TextInput style={styles.input} placeholder="Nome" value={nome} onChangeText={setNome} /> <TextInput style={styles.input} placeholder="Età" value={eta} onChangeText={setEta} keyboardType="numeric" maxLength={3} /> <Button title="Invia" onPress={invia} /> </View> );}
const styles = StyleSheet.create({ container: { flex: 1, justifyContent: 'center', alignItems: 'center', padding: 30, backgroundColor: '#f5f5f5', }, titolo: { fontSize: 24, fontWeight: 'bold', marginBottom: 20, }, input: { width: '100%', borderWidth: 1, borderColor: '#ccc', padding: 12, borderRadius: 8, fontSize: 16, marginBottom: 12, backgroundColor: 'white', }, dato: { fontSize: 18, marginBottom: 8, },});6. Multi-stato e validazione
Section titled “6. Multi-stato e validazione”const [email, setEmail] = useState('');const [password, setPassword] = useState('');const [errore, setErrore] = useState('');
const login = () => { if (!email) { setErrore('Inserisci l\'email'); return; } if (!password) { setErrore('Inserisci la password'); return; } if (password.length < 6) { setErrore('Password troppo corta (min 6 caratteri)'); return; } setErrore(''); Alert.alert('✅ Successo', 'Login effettuato!');};7. Stile condizionale
Section titled “7. Stile condizionale”// Cambia stile in base allo stato<TextInput style={[ styles.input, errore && styles.inputErrore, // ← bordo rosso se errore ]}/>
const styles = StyleSheet.create({ input: { borderWidth: 1, borderColor: '#ccc', padding: 12, borderRadius: 8, }, inputErrore: { borderColor: 'red', borderWidth: 2, },});8. Tabella riassuntiva
Section titled “8. Tabella riassuntiva”| Concetto | Codice |
|---|---|
| useState | const [x, setX] = useState(iniziale) |
| Aggiornare stato | setX(nuovoValore) |
| Bottone | <Button title="..." onPress={fn} /> |
| TextInput | <TextInput value={x} onChangeText={setX} /> |
| Alert | Alert.alert('Titolo', 'Messaggio') |
| Stile condizionale | style={[base, cond && extra]} |
9. Esercizio autonomo
Section titled “9. Esercizio autonomo”🎯 Esercizio: “App Convertitore € → $”
Section titled “🎯 Esercizio: “App Convertitore € → $””Crea un’app che:
- Un campo per importo in euro
- Un campo per il tasso di cambio (default: 1.08)
- Bottone “Converti”
- Mostra il risultato: X.XX € = Y.YY $
- Validazione: mostra errore se l’importo è vuoto o <= 0
- Quando il risultato > 100€, coloralo di verde
- Extra: bottone “Inverti” che scambia € e $
Suggerimenti
Section titled “Suggerimenti”keyboardType="decimal-pad"per numeri con virgolaparseFloat(valore)per convertire stringa → numero.toFixed(2)per arrotondare a 2 decimali