4. diel - React Native - Dokončenie TODO aplikácie
V minulej lekcii, React Native - TODO aplikácie , sme si vytvorili základnú funkčnosť TODO aplikácie.
Naposledy sme skončili pri props
. Začneme tým, že si
upravíme našu novú komponent TodoItem
. Poďme si teda ukázať,
ako to funguje a upravme si return
v súbore
components/TodoItem.js
nasledovne:
const TodoItem = (props) => { return ( <TouchableOpacity key={props.item.id} onPress={props.onToggleFinish.bind(this, props.item.id)} onLongPress={props.onDelete.bind(this, props.item.id)} > <View style={[styles.listItem, { backgroundColor: props.item.finished ? '#afa' : '#ccc' }]} > <Text>{props.item.description}</Text> </View> </TouchableOpacity> ); }
Využívame niekoľkých nových vecí ako je potrebné
TouchableOpacity
. Tento komponent slúži ako Button
a
uľahčuje nám štylizovanie a ďalšie veci. Tiež nám dovoľuje použiť
atribúty ako sú onPress
a onLongPress
. Ako je
možné vidieť, využívame props.onToggleFinish
a
props.onDelete
. Po krátkom kliknutí sa nám náš TODO task buď
splní, alebo znova stane aktívnym. Po dlhom stlačení sa daný TODO
zmaže.
Ďalej využívame View
, ktorý nám bude štylizovať TODO
tasky. Využívame pre neho tento štýl:
style={[styles.listItem, { backgroundColor: props.item.finished ? '#afa' : '#ccc' }]}
Najskôr použijeme predefinovanie štýl zo Stylesheet objektu, ktorý si za
chvíľu vytvoríme. Ďalej nastavujeme farbu pozadia podľa toho, či je TODO
hotové alebo nie. V komponente Text
si vypíšeme popis TODO
tasku.
Využívame teda atribúty onToggleFinish
, onDelete
a item
. Naši komponent budeme musieť teda používať zhruba
takto:
<TodoItem item={taskObject} onToggleFinish={toggleTaskHandler} onDelete={removeTaskHandler} />
Ako posledný si v našej komponente nadefinujeme Stylesheet objekt:
const styles = StyleSheet.create({ listItem: { padding: 10, marginVertical: 10, backgroundColor: '#ccc', borderColor: 'black', borderWidth: 1 } });
Teraz sa vráťme do súboru App.js
. Importujeme si nový
komponent TodoItem
:
import TodoItem from "./components/TodoItem"
Ďalej si upravme našu funkciu renderTaskItem
tak, aby sme
využili našu novú komponent:
const renderTaskItem = ({ item }) => { return ( <TodoItem item={item} onToggleFinish={toggleTask} onDelete={removeTaskHandler} /> ) }
A vytvorme si potrebné funkcie spomínané z kódu vyššie do hlavnej
funkcie App()
:
const removeTaskHandler = taskId => { setTaskArray(taskArray => taskArray.filter(task => task.id != taskId)) } const toggleTask = taskId => { /* Never mutate state directly, can cause a lot of issues */ let tmpArray = [...taskArray]; for (var i in tmpArray) { if (tmpArray[i].id == taskId) { tmpArray[i].finished = !tmpArray[i].finished; break; // Stop this loop, we found it! } } setTaskArray(tmpArray); }
Funkcia removeTaskHandler()
je vcelku jednoduchá, vyfiltruje
danej Todos, aby neobsahovali nami vymazanej tasky. Parameter
taskId
sme si nabindovali v našej komponente. Vo funkcii
toggleTask()
si najskôr skopírujeme naše polia Todos, aby sme ho
neupravovali napriamo. Ďalej v cykle for
nájdeme task, ktorý
chceme upraviť. Potom nami upravené poľa znova nastavíme ako naše nové
pole Todos. Keď si spustíme našu aplikáciu, môžeme si teraz pridávať
Todos, dokončovať ich alebo mazať:
Naša aplikácia je teraz úplne funkčný, avšak poďme si ju upraviť
ešte ďalej. Vytvoríme si nový komponent. Vytvorme si teda súbor
./components/TodoInput.js
.
Importujte si teda potrebné komponenty a vytvorme si základ:
import React, { useState } from 'react' import { View, TextInput, Button, StyleSheet, Modal } from 'react-native' const TodoInput = (props) => { return ( <Text>Hello World</Text> ); } export default TodoInput; const styles = StyleSheet.create({ });
Tento komponent bude slúžiť po náš input. Budeme využívať komponent
Modal
, ktorá slúži na vytvorenie obsahu nad naším základným
view
. Naši komponent budeme potom využívať nasledovne:
<TodoInput visible={isAddMode} onAddTask={addTaskHandler} onCancel={cancelGoalAdditionHandler} />
Tým pádom budeme skrz props
mať prístup k
visible
, onAddTask
a onCancel
. Budeme
potrebovať stavovú premenou, ktorá nám bude ukladať obsah nášho inputu,
ako sme to využívali v App.js
:
const TodoInput = (props) => { const [enteredTask, setEnteredTask] = useState(""); const taskInputHandler = (enteredText) => { setEnteredTask(enteredText); } ...
Teraz si poďme upraviť kód JSX, ktoré bude komponent generovať:
return ( <Modal visible={props.visible} animationType="slide"> <View style={styles.inputContainer}> <TextInput placeholder="Task description" style={styles.input} onChangeText={taskInputHandler} value={enteredTask} /> <View style={styles.buttonContainer}> <View style={styles.button}> <Button title="CANCEL" color="red" onPress={props.onCancel} /> </View> <View style={styles.button}> <Button title="ADD" onPress={() => { props.onAddTask(enteredTask); setEnteredTask("") }} /> </View> </View> </View> </Modal> );
Naša Modal
komponent bude obsahovať jeden
TextInput
a dva Button
. Správanie tlačidiel budeme
ovládať zase skrze props
. Upravme si ešte náš objekt
StyleSheet
, aby obsahoval naše vlastné štýly:
const styles = StyleSheet.create({ inputContainer: { flex: 1, justifyContent: 'center', alignItems: 'center' }, input: { width: '80%', borderColor: 'black', borderWidth: 1, padding: 10, marginBottom: 10 }, buttonContainer: { flexDirection: 'row', justifyContent: 'space-around', width: '60%' }, button: { width: '40%' } });
Naša komponenta je teraz hotová a môžeme sa vrátiť do súboru
App.js
. Už nebudeme potrebovať premennú enteredText
a funkciu taskInputHandler()
, tým pádom ich môžeme odstrániť.
Ďalej bude potrebné spravovať viditeľnosť našej nové komponenty. Na to
nám poslúži:
const [isAddMode, setIsAddMode] = useState(false);
Upravme si teda naše JSX vo funkcii App()
:
return ( <View style={styles.container}> {/* For simplification purpose we don't install SafeAreaView but use padding to make "fake" save SaveAreaView */} <Button title="Add New Task" onPress={() => setIsAddMode(true)} /> <TodoInput visible={isAddMode} onAddTask={handleAddTodo} onCancel={cancelTodoAdditionHandler} /> <FlatList renderItem={renderTaskItem} data={taskArray} keyExtractor={(item) => item.id} /> </View> );
Využívame našu novovytvorenú komponent, avšak ešte sme si ju neimportovali, tak to poďme urobiť:
import React, { useState } from 'react'; import { StyleSheet, View, Button, FlatList } from 'react-native'; import TodoItem from "./components/TodoItem" import TodoInput from "./components/TodoInput"
Ako posledný vec je potrebné upraviť našu funkciu
handleAddTodo()
a pridať novú funkciu
cancelTodoAdditionHandler()
:
const handleAddTodo = (enteredText) => { if (enteredText.length < 1) { return; } var task = { id: Math.random().toString(16).slice(-5), finished: false, description: enteredText } setTaskArray(tasks => [...tasks, task]); setIsAddMode(false); } const cancelTodoAdditionHandler = () => { setIsAddMode(false); }
Po spustení bude pridávanie TODO vyzerať nasledovne.
Gratulujem, vytvorili ste si prvú reálnu aplikáciu, ktorú môžete využívať. Pre dnešný lekciu je to teda všetko.
V budúcej lekcii, Pozíciovanie komponentov , si ukážeme a popíšeme absolútne a relatívne pozíciovanie, okraje, jednotky veľkostí a defaultné správanie komponentu View.