Header
Krenućemo sa pravljenjem našeg Header-a, zatim ćemo ga iskoristi u našoj aplikaciji i zatim ga stilizovati. Header će konstantno biti na vrhu ekrana i sadržati odredjeni tekst. Header predstavlja jednu našu komponentu koja, kako smo već rekli, sadrži JSX kod koji će se renderovati na ekranu uredjaja.
Kreiranje komponente
Praksa je (i to jako dobra i gotovo na svim projektima obavezna) da za svaku komponentu se pravi poseban fajl. Tako da ćemo za našu komponentu napraviti fajl `Header.js`. Pored toga, dobro je napraviti zaseban folder u kome će se nalaziti svi vaši fajlovi koje pravite kako bi se izdvojilo od ostalih potrebnih React Native fajlova. Zbog toga, u root folderu napravićemo folder `src` koji predstravlja folder u kome se nalazi naš kod, zatim u njemu pravimo folder `components` koji će sadržati naše komponente i zatim u tom folderu pravimo naš fajl `Header.js`. "Stablo" projekta u ovom trenutku ovako izgleda:
Za potrebe pravljenja nove komponente prvo ćemo importovati pogrebne biblioteke
import React from 'react';
import { Text } from 'react-native';
Zatim kreiramo komponentu
const Header = () => {
return (
<Text> Books! </Text>
);
};
Praksa je da ime komponente bude isto kao i ime fajla u kome se nalazi (Header).
I na kraju potrebno je mogućiti da ova komponenta bude dostupna ostalim delovima aplikacije. To omogućavamo time što export-ujemo komponentu.
export default Header;
Ideja je da imamo jednu *root* komponentu, koja je u ovom slučaju App komponenta u index fajlovima, i da samo nju registrujemo (kao što je već učinjeno), a da sve ostale komponente predstavljaju *child* komponente i njih exportujemo i tako omogućimo njihovo korišćenje u ostalim komponentama (u root-u npr).
Header komponenta treba da izgleda ovako :
Korišćenje komponente
Sledeći korak jeste da import-ujemo komponentu u fajl gde želimo da je koristimo. U ovom slučaju je to naša root komponenta App koja se nalazi u index fajlovima.
Znači u index.ios.js ili index.android.js import-ujemo Header komponentu
import Header from './src/components/Header;
Za razliku od modula koje smo pre import-ovali (iz react-a i react native-a), za naše module potrebno je da obezbedimo relativnu putanju. (./src/components/Header). Razlog postojanja ovakve razlike je u tome što su nazivi npm modula jedinstveni, dok mi možemo napraviti više komponenti sa istim nazivima pa da ne bi došlo grešaka obezbedjuje se puna putanja da bi se znalo na koji se modul tačno misli.
Sada kada je import-ovana, iskoristićemo Header komponentu unutar App komponent (ovo se naziva Component Nesting). Refaktorisaćemo našu App komponentu tako što ćemo obrisati <Text> i umesto tog taga iskoristi Header komponentu.
const App = () => {
return (
<Header />
);
};
Praksa je da ukoliko izmedju dva taga (<Header> </Header>) nema nikakvog teksta ili drugih tagova, koristi se "samozatvarajući" tag. ( <Header />).
Index fajlovi sada izgledaju ovako:
Stilizovanje komponente
Stilizovanje komponenti u React Native-u je škakljiva tema, ako ste radili na veb aplikacijama koristeći HTML i CSS upoznati ste sa bibliotekama kao što je bootstrap, jednostavno je ubacite u projekat iskoristite klase i dobijete sjajan izgled vaših elemenata, medjutim RN nema takvih biblioteka. (Postoje neki započeti projekti, ali daleko su od toga da se može reći da su to stabilne i biblioteke spremne za produkciju).
U suštini, u React Native-u uglavnom morate odraditi stilizovanje sami , što je i dobro uzimajući u vidu to da se mnogo toga može naučiti.
Jedan od načina da se stilizuje komponenta je da se umesto pravljenja novog css fajla sav stil pišemo unutar fajla same komponente.
const styles = { } ;
Praksa je da se ispod komponente napravi novi objekat sa imenom styles
unutar koga ćemo smeštati stil za svaki deo komponente. Znači, ne korisiti se CSS za stilizovanje već JavaScript. Imena i vrednosti su jako slična CSS-u osim što se koristi Camel Case (umesto npr backgroud-color koristimo backgroundColor).
const style = {
textStyle: {
fontSize: 20
}
};
Na ovaj način smo samo povećali veličinu fonta našeg teksta.
Nakon ispisanog stila, treba komponentama dodati pređašnje ispisan stil (kao što je dodavanje CSS "class"-a u HTML-u). To radimo pomoću atributa style u koji smeštamo ime objekta iz styles-a koji želimo da primenimo na našu komponentu. Pomoću dekonstrukcije unutar komponente "izlistamo" sve style objekte koji su nam potrebni i ubacimo ih kao style atribut na željena mesta.
Header sada ovako izgleda
const Header = () => {
const { textStyle } = styles;
return (
<Text style={ textStyle }>Books!</Text>
);
};
(Sada možete da reload-ujete simulator i videćete odgovarajuće promene).
Vreme je da se pozabavimo pozicioniranjem elemenata.
import { Text, View } from react-native; // Importujemo View element
const Header = () => {
const { textStyle } = styles;
return (
<View> // okružujemo naš stari Text element View elementom
<Text style={ textStyle }>Books!</Text>
</View>
);
};
Ukoliko hoćemo da centriramo neki element ili menjamo njegovu poziciju na bilo kakav način, najbolje je koristiti View tag koji je obezbeđen od strane React Native-a. To je jos jedan "primitivan" tag koji nam pomaže da "umotamo" elemente unutar njega, zatim ga pozicioniramo i stilizujemo. Stilizujemo ga isto prosleđujući određeni objekat kroz style property.
Dekonstrukcija se koristi samo da bi kod bio "čistiji" da se ne bi duplirala referenca na styles objekat. Da ovo ne radimo pisali bi styles.viewStyle... Dekonstrukcija nije obavezna, samo je dobra praksa.
Za pozicioniranje komponenti koristićemo Flexbox. To je sistem za pozicioniranje elemenata unutar kontejnera. U našem slucaju imamo kontejner koji je View i child elemment Text, sada mozemo koristeci Flexbox da kazemo kako želimo da se Text element ponaša unutar View elementa. Po default-u child elementi se nalaze u gornjem levom uglu. Više o Flexboxu u React native-u procitajte u dokumentaciji.
Pročitajte i zanimljiv post o Flexboxu.
viewStyle: {
justifyContent: 'center',
alignItems: 'center'
}
Jednostavno pomoću ova dva property-ja centriraćemo Text child element.
Zavisno od property-ja flexDirection , justifyContent i alignItems menjaju svoje ponašanje. (Po default-u vrednost flexDirection-a je "row" i tada justifyContent centrira elemente po vertikalnoj osi, dok alignItems to čini po horizontalnoj).
Dodaćemo još par property-ja kako bi stilizovali naš header.
viewStyle: {
backgroundColor: '#F8F8F8',
justifyContent: 'center',
alignItems: 'center',
height: 60,
paddingTop: 15,
shadowColor: '#000',
shadowOffset: { width: 0, height: 2 },
shadowOpacity: 0.4,
elevation: 2,
position: 'relative'
}
Za vise detalja o stilizovanju pogledajte React Native dokumentaciju.
Vaš Header.js treba ovako da izgleda :
I kada reload-ujete svoj simulator :
Reusable component
Poslednje što ćemo uraditi sa Header komponentom jeste da ćemo je učiniti reusable-ilnom. (Reusable component - Da se može koristiti na više mesta i više puta).
Kao što možete videti, za sada tekst unutar naše komponente je "hardcode"-ovan, tako da kada bi iskoristili ovu komponentu na bilo kom drugom mestu, i dalje bi tekst bio "Book" iako to možda ne želimo. Zato ćemo odraditi malo refaktorisanje koda, i omogućiti parent-u (elementu koji importuje i koristi naš element) da odlučuje šta će pisati unutar header-a. To ćemo učiniti koristeći props-e, tako što će "parent" prosledjivati property koji sadrži odgovarajući tekst.
U našem slučaju parent komponenta jeste App.
Ovo refaktorisanje obaviće se u tri koraka :
- Unutar child komponente identifikovati varijablu koja će biti dostavljena od strane parent-a.
- Obezbediti referencu do objekta props koji child komponenti stiže od strane parent-a
- Parent komponenta prosleđuje odgovarajući prop
const Header = (props) => { ... //obezbedjivanje reference do objekta props
Props je JavaScript objekat koji sadrži property-je koji su prosledjeni od strane parent-a i da bi napravili referencu na objekat unutar JSX-a koristimo vitičaste zagrade {} .
<Text style={ textStyle }>{ props.headerText }</Text>
I sada još nam ostaje da parent prosledi property sa nazivom headerText.
Nazivi ovakvih vaših property-ja mogu se zvati kako god želite, ovde je iskorišćen naziv headerText samo zbog logike.
const App = () => {
return (
<Header headerText="Books" />
);
};
Kada reload-ujete simulator, ne bi trebalo biti nikakvih promena, a napravili ste reusable-nu Header komponentu koju možete iskoristi bilo gde i samo je potrebno proslediti joj property headerText.