Sei sulla pagina 1di 8

1.

React.js: generic Javascript library per lo sviluppo di interfacce


React.DOM: parte di React che si occupa di renderizzare interfacce in ambito HTML
React Native: insieme di React Component che vengono compilati da React come native
widget Android o iOS
Permette anche di accedere ad API native e.g. per la gestione di camera.
E’ possibile anche scrivere codice nativo, React Native permette di connettere codice nativo
con codice javascript.

Quindi usando React.js + React Native posso sviluppare app native per mobile.

4.

In pratica solo la parte di UI viene compilata; tutta la logica rimane in js e viene interpretata
da una VM che esegue in un thread dedicato all’interno dell’app

5.
Per sviluppare un’app posso usare o Expo o React Native CLI: Expo è più facile, meno
performante e meno fine-tunable, ma ottimo per iniziare. Nel caso, si può passare in un
secondo tempo a React Native CLI (‘eject’)

Con Expo, per creare una nuova app, lancio da shell:


$ expo init nome-app

Javascript refresher

Arrow functions
const myFunc = (arg1, arg2) => {
return arg1 + arg2
}

Se ho solo la direttiva return nel corpo della funzione, posso omettere le graffe e la keyword
return:
const myFunc = (arg1, arg2) => arg1 + arg2

Se ho un solo parametro posso omettere le tonde attorno ai parametri:


const myFunc = arg1 => arg1 + 10

Se non ho parametri:
const myFunc = () => 5 + 10

Operatori spread e rest

Spread: utilizzato per “estrarre” tutti gli elementi di un array o di un oggetto:


const arr = [1,2,3]
console.log(...arr);

const person = { age : 30, name : ‘saverio’ }


copiedPerson ={ ...person }

Rest: permette ad una funzione di accettare un numero variabile di parametri


const cane = (...args) => {
let out = 0
for (let elem of args) {
out += elem

}
return out
}

Destructuring assignment
Permette di spacchettare elementi singoli di oggetti o array

Object destructuring:
const person = { age : 22, name : 'dio', isGod : true}

const printName = ({ name, age }) => {


console.log(name + “ ha ” + age + “ anni”)
}

printName(person)
specifico il nome degli attributi a cui sono interessato

Posso anche spacchettare gli attributi:


const {age, isGod} = person;

console.log(isGod)
Nota: quando spacchetto devo mantenere i nomi degli attributi.

Array destructuring:
const cane = [1,2,3,4,5]
const [a, b, ...rest] = cane
console.log(a)
console.log(rest)

Nota: …rest lo posso usare anche con l’object destructuring

React

Component:
un component può essere:
una funzione che ritorna del JSX oppure una serie di istruzioni React.createElement
una classe che ha un metodo render che ritorna del JSX oppure una serie di istruzioni
React.createElement

Nota: posso usare JSX, oppure posso importare direttamente un css in un file .js perché
react sa parsare queste cose e produce codice js nativo. E’ per quello che devo fare
Import React from ‘react’ anche se non uso nulla dalla classe React

Nota: i file css hanno scope globale, a prescindere da dove li metto e in che file li importo;
tutti i component della mia app vedono tutti i css

Per usare codice js in JSX lo racchiudo tra {}

Renderizzare liste di dati:


utilizzo la funzione map su un array che contiene tutti i dati che voglio renderizzare in un
certo modo. Esempio:

const GoalList = props => {


return (
<ul className="goal-list">
{props.goals.map(goal => {
return <li key={goal.id}>{goal.text}</li>;
})}
</ul>
);
};

export default GoalList;

goals è un array che passo come prop al functional component GoalList; per renderizzarlo ci
chiamo sopra map.
Comunicazione tra component:
Se devo passare dati dal parent component al child component li passo come props

Se devo passare dei dati da un child component al parent component invece, definisco una
callback nel parent che passo al child come prop, in cui scrivo cosa fare con i dati.
Esempio:
Il parent è App
const App = () => {
const courseGoals = [];

const addNewGoalHandler = newGoal => {


courseGoals.push(newGoal);
console.log(courseGoals);
};

return (
<div className="course-goals">
<h2>Course Goals</h2>
<NewGoal onAddGoal={addNewGoalHandler} />
<GoalList goals={courseGoals} />
</div>
);
};

il Child è NewGoal
const NewGoal = props => {
const addGoalHandler = event => {
event.preventDefault();

const newGoal = {
id: Math.random().toString(),
text: 'My new goal!'
};

props.onAddGoal(newGoal);
};

return (
<form className="new-goal" onSubmit={addGoalHandler}>
<input type="text" />
<button type="submit">Add Goal</button>
</form>
);
};

In partica NewGoal renderizza un input che permette di scrivere il testo per un nuovo goal e
un bottone per salvarlo. All’evento del bottone associo addGoalHandler, che al suo interno
richiama la callback definita nel parent, accedendola attraverso le props: props.onAddGoal.

Stato
React usa lo stato per capire quando deve ri-renderizzare qualcosa: se una variabile nello
stato cambia valore, tutti i component che la usano vengono ri-renderizzati
automaticamente
React mette a disposizione funzioni specifiche per gestire lo stato, dette hook functions, che
possono essere usate solo dentro functional components. Per ogni variabile che vogliamo
inserire nello stato di un component, uso la hook function useState:
const [variable_name, set_function] = useState(intial_value).
Dove: variable_name contiene l’ultimo snapshot dello stato, e set_function è la funzione che
permette di modificarlo.
Nota: set_function prende come parametro un nuovo oggetto, non modifica quello
attualmente presente nello stato (lo sovrascrive con quello nuovo)
App lo possiamo riscrivere così:
const App = () => {
const [courseGoals, setCourseGoals] = useState([
{ id: 'cg1', text: 'Finish the Course' },
{ id: 'cg2', text: 'Learn all about the Course Main Topic' },
{ id: 'cg3', text: 'Help other students in the Course Q&A' }
]);

const addNewGoalHandler = newGoal => {


setCourseGoals(prevCourseGoals.concat(newGoal));
};

return (
<div className="course-goals">
<h2>Course Goals</h2>
<NewGoal onAddGoal={addNewGoalHandler} />
<GoalList goals={courseGoals} />
</div>
);
};
Nota: se il nuovo stato dipende da quello precedente, alla mia set_function devo passare
una funzione, che prende in input lo stato precedente e ne ritorna uno nuovo:
setCourseGoals(prevCourseGoals => prevCourseGoals.concat(newGoal));
Questo metodo mi assicura anche, in applicazioni con molti cambi di stato simultanei, che i
questi cambi avvengano nell’ordine corretto.

Form management e two-way binding


Per gestire campi di form si usa ancora lo stato:
const NewGoal = props => {
const [enteredText, setEnteredText] = useState('');

const addGoalHandler = event => {


event.preventDefault();

const newGoal = {
id: Math.random().toString(),
text: enteredText
};
setEnteredText('');

props.onAddGoal(newGoal);
};

const textChangeHandler = event => {


setEnteredText(event.target.value);
};

return (
<form className="new-goal" onSubmit={addGoalHandler}>
<input type="text" value={enteredText} onChange={textChangeHandler} />
<button type="submit">Add Goal</button>
</form>
);
};

il campo testo ha due binding allo stato: da una parte, il suo valore è legato a quello di
enteredText, che è la variabile inserita nello stato del component. Dall’altro, quando il
valore del campo cambia viene chiamata la funzione textChangeHandler che, al suo interno,
richiama setEnteredText per modificare il valore dello stato.

React Native Fundamentals


In React Native uso dei core components per creare la mia UI (tipo <Button>, <Touchable>)
Per lo styling dei component uso la sintassi simil-css di React standard, attraverso:
 inline styles
 StyleSheet objects

Per iniziare una nuova app, da terminale: expo init APPNAME


Nel terminale di Visual Studio Code, vado nella dir del progetto e lancio npm start. In questo
modo vedo tutti gli errori generati dall’app nell’IDE

Core components:
<View> è come un div
<Text> contiene del testo. Non è possibile mettere testo in un’app se non racchiuso tra i tag
<Text>

FlexBox:
utilizzato per posizionare i child elements di una view
permette di organizzare i child di una view o su una riga o su una colonna (default)
flexDirection: può essere row, column o row-reverse, column-reverse per invertire l’ordine
dei child
La flexDirectione specifica la main axis; la cross axis è l’opposto (cross axis di column è row,
cross axis di row-reverse è row-column)
se non specifico width e height dei child, occuperanno il minimo indispensabile perché il
loro contenuto possa essere visualizzato
Se specifico width e height della parent view, nel caso i child non abbiano dimensioni
specificate, assumono l’height del parent, mentre il width rimane immutato
Per organizzare i miei child lungo la main axis uso justifyContent; per organizzarli lungo la
cross axis uso alignItems
Il comportamento di default è che i child si organizzano lungo la cross axis stretchandosi; se
voglio farli stretchare anche lungo la main axis non posso usare stretch come valore di
justifyContent, ma devo agire sul singolo child: specifico l’attributo flex all’interno
dell’oggetto StyleSheet del child, e gli assegno un valore. Il valore è un numero relativo tra
tutti i child.

Il modo consigliato di dichiarare proprietà di stile, è quello di creare un oggetto Stylesheet


che funge da container ai vari fogli di stile.
const styles = StyleSheet.create({
screen: {
padding: 30
},
inputContainer: {
flexDirection: 'row',
justifyContent: 'space-between',
alignItems: 'center'
},
input: {
width: '80%',
borderColor: 'black',
borderWidth: 1,
padding: 10
}
});

e poi li uso così:


<View style={styles.screen}>
<View style={styles.inputContainer}>
<TextInput
placeholder="cane"
style={styles.input}
/>
<Button title="Add" />
</View>
</View>

ScrollView component: da utilizzare al posto di una View se voglio che sia scrollabile in caso
di overflow del contenuto

FlatList component: più performante di ScrollView, da preferire quando non si conosce a


priori quanti elementi andranno renderizzati (e.g. una lista dinamica) oppure quando c’è un
alto numero di elementi. Flatlist ha come props obbligatorie:
data: l’array da renderizzare
renderItem: una funzione che viene richiamata per renderizzare ogni singolo
elemento.
Nota: FlatList si aspetta gli elementi da renderizzare come oggetti che hanno un
attributo ‘key’ univoco.
<FlatList
data={courseGoals}
renderItem={
itemList => {
return <View style={styles.listItem}>
<Text>{itemList.item.value}</Text>
</View>
}
}
/>

Nel caso abbia già degli oggetti che non hanno un attributo ‘key’ o ‘id’ (riconosciuti da react
come indici univoci), devo passare a FlatList un keyExtractor. Supponendo che i miei oggetti
abbiamo un attributo chiave che si chiama ‘cane’, devo fare:
<FlatList
keyExtractor = {(item, index) => item.cane}
data={courseGoals}
renderItem={
itemList => {
return <View style={styles.listItem}>
<Text>{itemList.item.value}</Text>
</View>
}
}
/>

Se una callback che passo ad un component necessita di essere chiamata con un attributo,
uso il metodo bind:
const GoalItem = props => {
return (
<TouchableOpacity onPress={props.onDelete.bind(this,props.id)}>
<View style={styles.listItem}>
<Text>{props.title}</Text>
</View>
</TouchableOpacity>
)
};

In questo caso onDelete, dichiarata nel component padre, richiede un parametro.

3.
Debug: Per usare React Native Debugger, prima devo lanciarlo, poi sullo smartphone, in
Expo, gli dico “Debug appication”.

Potrebbero piacerti anche