Todo 앱 실습 - 3

박태영·2024년 5월 17일

react-native 실습

목록 보기
10/11

목표

  1. toDo 가 여행인지 할일인지에 따라 구별하여 랜더링하기
  2. AsyncStorage를 이용해서 재실행 되더라도 기록 유지하기

1.

{Object.keys(toDos).map((key) =>
          toDos[key].working === working ? (
            <View style={styles.toDo} key={key}>
              <Text style={styles.toDoText}>{toDos[key].text}</Text>
            </View>
          ) : null
        )}
  • Object.keys()로 오브젝트의 키 배열을 만들어 map으로 순환
  • toDos[key].working 값이 true/false 인지따라서 랜더링을 결정하면 구별하여 랜더링할 수 있다.

2

  1. AsyncStorage 설치

터미널에 입력
npx expo install @react-native-async-storage/async-storage

ℹ️ AsyncStorage?

  • 비동기, 암호화되지 않은, 영구적인 키-값 저장소 API를 제공하는 라이브러리.
  • 브라우저의 localStorage 와 동일한 역할을 한다.
  1. AsyncStorage를 이용해서 저장/로드하는 함수를 구성
 const saveToDos = async (toSave) => {
   //데이터를 받아와 AsyncStorage에 저장
    await AsyncStorage.setItem(STORAGE_KEY, JSON.stringify(toSave));
  };
  const loadToDos = async () => {
    //가지고온 데이터를 파싱하여 state에 저장
    const s = await AsyncStorage.getItem(STORAGE_KEY);
    setToDos(JSON.parse(s));
  };

3.useEffect를 이용해 rendering이 끝나고 나서 loadToDos함수를 불러 다시 state에 값을 세팅하기

  useEffect(() => {
    loadToDos();
  }, []);

전체 코드

import { StatusBar } from "expo-status-bar";
import {
  StyleSheet,
  Text,
  View,
  TouchableOpacity,
  TextInput,
  ScrollView,
} from "react-native";
import theme from "./colors";
import { useEffect, useState } from "react";
import AsyncStorage from "@react-native-async-storage/async-storage";
const STORAGE_KEY = "@toDos";
export default function App() {
  const [working, setWorking] = useState(true);
  const [text, setText] = useState("");
  const [toDos, setToDos] = useState({});
  const travel = () => setWorking(false);
  const work = () => setWorking(true);
  const onChangeText = (payload) => setText(payload);
  useEffect(() => {
    loadToDos();
  }, []);
  const addToDo = async () => {
    if (text === "") {
      return;
    }
    //save to do
    const newToDos = { ...toDos, [Date.now()]: { text, working } };
    setToDos(newToDos);
    saveToDos(newToDos);
    console.log(newToDos);
    setText("");
  };
  const saveToDos = async (toSave) => {
    await AsyncStorage.setItem(STORAGE_KEY, JSON.stringify(toSave));
  };
  const loadToDos = async () => {
    const s = await AsyncStorage.getItem(STORAGE_KEY);

    setToDos(JSON.parse(s));
  };

  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>

      <TextInput
        text={text}
        onSubmitEditing={addToDo}
        onChangeText={onChangeText}
        returnKeyType="done"
        value={text}
        style={styles.input}
        placeholder={working ? "Add a To Do" : "Where do you want to go?"}
      />
      <ScrollView>
        {Object.keys(toDos).map((key) =>
          toDos[key].working === working ? (
            <View style={styles.toDo} key={key}>
              <Text style={styles.toDoText}>{toDos[key].text}</Text>
            </View>
          ) : null
        )}
      </ScrollView>
    </View>
  );
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    backgroundColor: theme.bg,
    paddingHorizontal: 20,
  },
  header: {
    justifyContent: "space-between",
    flexDirection: "row",
    marginTop: 100,
  },
  btnText: {
    fontSize: 44,
    fontWeight: "600",
  },
  input: {
    backgroundColor: "white",
    paddingVertical: 10,
    paddingHorizontal: 20,
    borderRadius: 30,
    marginVertical: 20,
    fontSize: 18,
  },
  toDo: {
    backgroundColor: theme.toDoBg,
    marginBottom: 10,
    paddingVertical: 20,
    paddingHorizontal: 20,
    borderRadius: 15,
  },
  toDoText: {
    color: "white",
    fontSize: 16,
    fontWeight: "500",
  },
});

실행 화면

profile
어른 아이

0개의 댓글