์๋ก์ด ํ๋ก์ ํธ๋ฅผ ์์ํ๋ค.
code .์ ํตํด์ vscode๋ฅผ ์ด์ด์ค๋ค.
์ด๋ฒ ํ๋ก์ ํธ๋ React Natvie
TouchableOpacity์ ์ฌ์ฉํด๋ณผ๊ฒ
https://reactnative.dev/docs/touchableopacity
TouchableOpacity · React Native
If you're looking for a more extensive and future-proof way to handle touch-based input, check out the Pressable API.
reactnative.dev
App.js๋ฅผ ์๋์ ๊ฐ์ด ์์ ํด์ค๋ค.
expo์ฑ์ผ๋ก ์คํํ๋ค.
์ฑ์๋ ์๋์ ๊ฐ์ด ์ถ๋ ฅ๋จ.
-> press here์ ํด๋ฆญํ๋ฉด ์์ count๊ฐ ์ฆ๊ฐ
import { StatusBar } from "expo-status-bar";
import { useState } from "react";
import { StyleSheet, Text, TouchableOpacity, View } from "react-native";
import { theme } from "./color";
export default function App() {
return (
<View style={styles.container}>
<StatusBar style="auto" />
<View style={styles.header}>
<TouchableOpacity>
<Text style={styles.btnText}>Work</Text>
</TouchableOpacity>
<TouchableOpacity>
<Text style={styles.btnText}>Travel</Text>
</TouchableOpacity>
</View>
</View>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: theme.bg, //ํ
๋ง ์ ์ฉ
paddingHorizontal: 20,
},
header: {
justifyContent: "space-between",
flexDirection: "row",
marginTop: 100,
},
btnText: {
fontSize: 38,
fontWeight: "600",
color: "white",
},
});
color.js๋ฅผ ๋ง๋ค์ด์ ํ
๋ง๋ฅผ ์ ์ฉํ๋ค.
export const theme = {
bg: "black",
grey: "#3A3D40",
};
ํฐ์น๊ฐ ์ ๋๋์ง ํ์ธํ๋ค.
usestate๋ฅผ ์ถ๊ฐํ๋ค.
๊ทธ๋ฆฌ๊ณ ํด๋ฆญํ ์ํ์ ๋ฐ๋ผ ์คํ์ผ์ ์ ์ฉํ๋ค. ๊ธฐ๋ณธ๊ฐ์ true-
Work ๋ฒํผ์ TouchableOpacity ์ onpress์ผ ๊ฒฝ์ฐ work ํจ์ ์คํ
workํจ์๋ working๋ฅผ true๋ก ์ ์ฅํ๋ค.
Travle ๋ฒํผ์ TouchableOpacity ๋ฅผ onpressํ ๊ฒฝ์ฐ travle ํจ์ ์คํ
working์ false๋ก ์ ์ฅํ๋ค.
z
import { StatusBar } from "expo-status-bar";
import { useState } from "react";
import { StyleSheet, Text, TouchableOpacity, View } from "react-native";
import { theme } from "./color";
export default function App() {
const [working, setWorking] = useState(true);
const travel = () => setWorking(false);
const work = () => setWorking(true);
return (
<View style={styles.container}>
<StatusBar style="auto" />
<View style={styles.header}>
<TouchableOpacity onPress={work}>
<Text
style={{ ...styles.btnText, color: working ? "white" : theme.grey }}
>
Work
</Text>
</TouchableOpacity>
<TouchableOpacity onPress={travel}>
<Text
style={{
...styles.btnText,
color: !working ? "white" : theme.grey,
}}
>
Travel
</Text>
</TouchableOpacity>
</View>
</View>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: theme.bg, //ํ
๋ง ์ ์ฉ
paddingHorizontal: 20,
},
header: {
justifyContent: "space-between",
flexDirection: "row",
marginTop: 100,
},
btnText: {
fontSize: 38,
fontWeight: "600",
color: "white",
},
});
work๋ฅผ ํด๋ฆญํ๋ฉด Work ๋ฒํผ์ font ์์์ด ํฐ์์ผ๋ก ๋ณ๊ฒฝ
Travel ์ ํด๋ฆญ ์ Travle ์์์ด ํฐ์์ผ๋ก ๋ณ๊ฒฝ๋๋ค.
https://reactnative.dev/docs/textinput
TextInput · React Native
A foundational component for inputting text into the app via a keyboard. Props provide configurability for several features, such as auto-correction, auto-capitalization, placeholder text, and different keyboard types, such as a numeric keypad.
reactnative.dev
์ด๋ฒ์๋ ๋ฒํผ์๋์ textInput์ ์ถ๊ฐํ ๊ฑฐ์
TouchableOpacity ์๋์ TextInput์ ์ถ๊ฐํ๋ค.
</Text>
</TouchableOpacity>
</View>
<View>
<TextInput
placeholder={working ? "ํ ์ผ ์ถ๊ฐ" : "์ด๋๋ก ์ฌํ ๊ฐ๊น์?"}
style={styles.input}
/>
</View>
</View>
input: {
backgroundColor: "white",
paddingVertical: 15,
paddingHorizontal: 20,
borderRadius: 30,
marginTop: 20,
fontSize: 18,
},
์๋๋ ์์ด๋ก ๋์ด์๋๋ฐ
Work์ ํ ์์๋ ํ ์ผ ์ถ๊ฐ
Travle์ ์ ํ ์์๋ ์ด๋๋ก ์ฌํ ๊ฐ๊น์?
placeholder๋ก ์ถ๋ ฅ๋จ
์๋์ ๊ฐ์ด keyboardType์ ๋ณ๊ฒฝํ ์ ์๋ค(์ฐธ๊ณ ๋ง ํ๊ธฐ )
๊ทธ๋ฆฌ๊ณ input์ด ๋ณ๊ฒฝ๋ ๋๋ง๋ค state์ text๋ฅผ ์ ์ฅํ๋๋ก
useState์ ํจ์๋ฅผ ์ถ๊ฐํ๋ค.
const [text, setText] = useState("");
const onChangeText = (payload) => setText(payload);
<View>
<TextInput
onChangeText={onChangeText}
value={text}
placeholder={working ? "ํ ์ผ ์ถ๊ฐ" : "์ด๋๋ก ์ฌํ ๊ฐ๊น์?"}
style={styles.input}
/>
</View>
๊ทธ๋ฆฌ๊ณ ํค๋ณด๋์์ ํ ์ผ์ ์
๋ ฅํ๊ณ <์๋ฃ>๋ฅผ ๋๋ฅด๋ฉด alert์ฐฝ์ด ์ถ๋ ฅ๋๊ฒ ํ
์คํธํ๋ค.
//์๋ฃ ๋๋ฅด๋ฉด ์คํ
const addTodo = () => {
if (text === "") return;
alert(text);
};
<View>
<TextInput
onSubmitEditing={addTodo}
returnKeyLabel="์๋ฃ"
onChangeText={onChangeText}
value={text}
placeholder={working ? "ํ ์ผ ์ถ๊ฐ" : "์ด๋๋ก ์ฌํ ๊ฐ๊น์?"}
style={styles.input}
/>
</View>
์์๊ฐ์ด alert์ฐฝ์ด ์ ์์ ์ผ๋ก ์ถ๋ ฅ๋๋ฉด
addTodo ํจ์๋ฅผ ์์ ํ๋ค.
const [toDos, setToDos] = useState([]);
//์๋ฃ ๋๋ฅด๋ฉด ์คํ
const addTodo = () => {
if (text === "") return;
const newTodo = {
id: Date.now(),
text: text,
working: working,
};
setToDos((prev) => [...prev, newTodo]); //๊ธฐ์กด์ ์ผ์ ์ ์ถ๊ฐํจ
setText(""); // text ์ด๊ธฐํ
// console.log(toDos);
};
๊ทธ๋ฆฌ๊ณ ์
๋ ฅํ todos๋ฅผ map์ผ๋ก ๋ฐ๋ณตํ์ฌ ๋ชจ๋ ์ถ๋ ฅํ๋ค.
์คํฌ๋กค ๋ทฐ๋ฅผ ์ฌ์ฉํ๋ค.
<View>
<TextInput
onSubmitEditing={addTodo}
returnKeyLabel="์๋ฃ"
onChangeText={onChangeText}
value={text}
placeholder={working ? "ํ ์ผ ์ถ๊ฐ" : "์ด๋๋ก ์ฌํ ๊ฐ๊น์?"}
style={styles.input}
/>
<ScrollView>
{toDos.map((todo) => (
<View style={styles.toDo} key={todo.id}>
<Text style={styles.toDoText}>{todo.text}</Text>
</View>
))}
</ScrollView>
</View>
input: {
backgroundColor: "white",
paddingVertical: 15,
paddingHorizontal: 20,
borderRadius: 30,
marginVertical: 20,
fontSize: 18,
},
toDo: {
backgroundColor: theme.grey,
marginBottom: 10,
paddingVertical: 20,
paddingHorizontal: 20,
borderRadius: 15,
},
toDoText: {
color: "white",
fontSize: 16,
fontWeight: "500",
},
๊ทธ ์ดํ
Work๋ฅผ ํด๋ฆญํ๋ฉด Work์ ๋ฑ๋กํ ํ ์ผ์ด ์ถ๋ ฅ๋์ผํ๊ณ
Travel์ ํด๋ฆญํ๋ฉด Travle์ ์ถ๊ฐํ ํ ์ผ์ด ์ถ๋ ฅ๋์ผํ๋ค.
<ScrollView>
{toDos.map((todo) =>
todo.working === working ? (
<View style={styles.toDo} key={todo.id}>
<Text style={styles.toDoText}>{todo.text}</Text>
</View>
) : null
)}
</ScrollView>
๋ก์ปฌ์ ์ ์ฅ
https://docs.expo.dev/versions/latest/sdk/async-storage/
AsyncStorage
A library that provides an asynchronous, unencrypted, persistent, key-value storage API.
docs.expo.dev
import ํ๊ธฐ
import AsyncStorage from "@react-native-async-storage/async-storage";
//์ฒ์ ํ ๋ฒ๋ง ์คํ
useEffect(() => {
loadToDos();
}, []);
// ๋ก์ปฌ ์คํ ๋ฆฌ์ง์์ ์ถ๊ฐ๋ ํ ์ผ ๊ฐ์ ธ์ค๊ธฐ
const loadToDos = async () => {
try {
const s = await AsyncStorage.getItem("my-todos");
setToDos(s != null ? JSON.parse(s) : []); //null์ด ์๋๋ฉด json.parse๋ฅผ ํตํด ๊ฐ์ฒด๋ก ๋ณํํ๊ณ null์ด๋ฉด ๋น ๋ฐฐ์ด
} catch (e) {
console.log(e);
}
};
// ๋ก์ปฌ ์คํ ๋ฆฌ์ง์ todo ์ ์ฅ
const saveToDos = async (toSave) => {
try {
await AsyncStorage.setItem("my-todos", JSON.stringify(toSave));
} catch (e) {
console.log(e);
}
};
addTodo ์์
//์๋ฃ ๋๋ฅด๋ฉด ์คํ
const addTodo = async () => {
//์๋ฌด๊ฒ๋ ์
๋ ฅํ์ง ์์์ผ๋ฉด ๋ฆฌํดํ๋ค.
if (text === "") return;
const newTodo = {
id: Date.now(),
text: text,
working: working,
};
//์ ํ ์ผ๋ค
const newTodos = [...toDos, newTodo];
setToDos(newTodos);
setText("");
//๋ก์ปฌ์ ์ ์ฅํ๊ธฐ
await saveToDos(newTodos);
};
todos๋ฅผ saveToDos์ ์ ์ฅํ๋ฉด ์
๋ฐ์ดํธ๊ฐ ์๋ ์ํ๋ก ์ ์ฅ์ด ๋ ์ ์์
๊ทธ๋์ ๋ฐ๋ก newTodos๋ก ์
๋ฐ์ดํธํ๋ค.
r๋ก ํ๋ก์ ํธ ์ฌ ์คํ์ ํ์ฌ ํ ์ผ์ ์ถ๊ฐํ๊ณ ๋ค์
r๋ก ์ฌ์คํ ์ ๋ฐ์ดํฐ๊ฐ ์ ์ง๋๋์ง ํ์ธํ๋ค.
์ญ์ ์์ด์ฝ์ ์ถ๊ฐํ๋ค.
<ScrollView>
{toDos.map((todo) =>
todo.working === working ? (
<View style={styles.toDo} key={todo.id}>
<Text style={styles.toDoText}>{todo.text}</Text>
<TouchableOpacity>
<Text>โ</Text>
</TouchableOpacity>
</View>
) : null
)}
</ScrollView>
์คํ์ผ๋ ์ถ๊ฐํด์ค๋ค.
toDo: {
backgroundColor: theme.grey,
marginBottom: 10,
paddingVertical: 20,
paddingHorizontal: 20,
borderRadius: 15,
flexDirection: "row",
alignItems: "center",
justifyContent: "space-between",
},
ํฌ๋ฆฌ๊ณ x์์ด์ฝ์ ํด๋ฆญํ๋ฉด ๋ก์ปฌ์คํ ๋ฆฌ์ง์์ ์ญ์ ๊ฐ ์คํ๋๋ก
๋ฉ์๋๋ฅผ ์ถ๊ฐํ๋ค.
filter๋ ์๋ก์ด ๋ฐฐ์ด์ ๋ง๋ค์ด์ค
์ญ์ ํ ํ ์ผ์ id์ ๊ฐ์ง ์์ ์ผ์ ๋ค๋ก๋ง ๊ตฌ์ฑ
//์ญ์ ๋ฉ์๋
const deleteTodo = (id) => {
const newTodos = toDos.filter((todo) => todo.id !== id);
setToDos(newTodos); //state์ ์ ์ฅ
saveToDos(newTodos); //๋ก์ปฌ ์คํ ๋ฆฌ์ง์์ ์ฅ
};
<ScrollView>
{toDos.map((todo) =>
todo.working === working ? (
<View style={styles.toDo} key={todo.id}>
<Text style={styles.toDoText}>{todo.text}</Text>
<TouchableOpacity onPress={() => deleteTodo(todo.id)}>
<Text>โ</Text>
</TouchableOpacity>
</View>
) : null
)}
</ScrollView>
๋ฐฐํฌํ๊ธฐ
Create your first build
Learn how to create a build for your app with EAS Build.
docs.expo.dev