본문 바로가기
App Study/React Native

노마드코더 리액트 네이티브 - 5

by 쿠리의일상 2023. 5. 30.

지금껏 입력 받은 내용을 onSubmitEditing 이벤트로 returnKey 입력을 감지하여 object 에 담아줬다.

이 값을 todos 에 객체 형태로 저장하고 Date.now() 를 키로 전개시켰는데

 

<ScrollView 
    contentContainerStyle={styles.scrollView}
    showsVerticalScrollIndicator={false}
    >
    {Object.keys(todos).map((el, idx) => {
      return (
      <View style={styles.todo}>
        <Text key={el} style={styles.todoText}>
          {idx+1}. {todos[el].text}
        </Text>
      </View>
      );
    })}
</ScrollView>

이렇게 object에 유일한 키로 저장한 값은 Object.keys(객체) 로 키 전체를 반환하는 배열을 받아줄 수 있으며,

이를 통해서 map 으로 반복문을 돌린다.

이때 map 의 값은 키로 받아온 것들이므로 todos에 대괄호로 키에 직접 접근해주고 text 내용을 받아온다.

 

이제 travel 의 값도 todo와 동일하게 처리해주면 된다.

 

<ScrollView 
    contentContainerStyle={styles.scrollView}
    showsVerticalScrollIndicator={false}
  >
    {Object.keys(todos).map((el, idx) => {
      return (
        todos[el].working === working ?
          <View key={el} style={styles.todo}>
            <Text style={styles.todoText}>
              {todos[el].text}
            </Text>
          </View>
        : null
      );
    })}
</ScrollView>

여기서 포인트는 submit 됐을 때 실행되는 이벤트 함수에 working 의 값을 반대로 주는 것

const addTodo = () => {
    if (text === '') return;

    if(working) {
      const newTodos = { 
        ...todos,
        [Date.now()] : {
          text,
          working }
      };
      setTodos(newTodos);
    } else {
      const newTravels = {
        ...travels,
        [Date.now()] : {
          text,
          working : !working,
        }
      }
      setTravels(newTravels);
    }
    
    setText('');
  }

 

일단 프론트적인 기능을 일단락 지어졌음

 

 

이제 사용자가 앱을 사용하면서 자리를 비우거나 앱을 잠시 끄는 등의 행동을 해서 앱이 재부팅 되더라도 입력해준 값이 남아있어야 하는데,

이를 위한 스토리지가 존재함

 

https://react-native-async-storage.github.io/async-storage/docs/install

 

Installation | Async Storage

Install

react-native-async-storage.github.io

AsyncStorage

npm install @react-native-async-storage/async-storage

 

사용법은 간단하다.

import AsyncStorage from '@react-native-async-storage/async-storage';

// ...
const storeStringData = async (strVal) => {
	try {
    	await AsyncStorage.setItem('key', strVal);
    } catch(e) {
    	// ...
    }
}

/////

const storeJsonData = async (val) => {
	try {
    	const jsonVal = JSON.stringify(val);
    	await AsyncStorage.setItem('key, jsonVal);
    } catch (e) {
    	// ...
    }
}

 

웹의 localStorage 를 사용하듯이 사용해줄 수 있되, 비동기적으로 처리해줘야 한다.(async await)

setItem(키, 값) 으로 저장

getItem(키) 로 값을 읽어올 수 있음

const getStringData = async () => {
	try {
    	const val = await AsyncStorage.getItem('키');
        if (val !== null) return val;
    } catch(e) {
    	// ...
    }
}

////

const getJsonData = async () => {
  try {
    const jsonVal = await AsyncStorage.getItem('키')
    return jsonVal !== null ? JSON.parse(jsonVal) : null;
  } catch(e) {
    // ...
  }
}

 

위의 내용으로 리스트들을 저장해주게끔 하자면,

  const saveTodos = async (val) => {
    try {
      await AsyncStorage.setItem(STORAGE_KEY, JSON.stringify(val));
    } catch(err) {
      throw err;
    }
  }
  
  const loadTodos = async () => {
    try {
      const result = await AsyncStorage.getItem(STORAGE_KEY);
      const data = JSON.parse(result);
      setTodos(data);

    } catch (err) {
      throw err;
    }
  }

저장할 땐 JSON.stringify() 로 object 를 문자로 바꿔주기

읽어올 땐 JSON.parse() 로 문자를 object 로 바꿔준다.

 

 

https://react-native-async-storage.github.io/async-storage/docs/api

 

API | Async Storage

getItem

react-native-async-storage.github.io

 

삭제를 구현하기 위해선 removeItem(키) 가 있다는데 todo의 하나만 삭제하는 것이므로

해당 함수가 아닌 원래 todos 리스트를 변경시키고 setItem() 해줄 것임

  const removeTodos = async (key) => {
    try {
      Reflect.deleteProperty(todos, key);
      await saveTodos(todos);
      loadTodos();
    } catch(err) {
      throw err;
    }
  }

Reflect/deleteProperty() 로 원래 객체에서 키로 찾아내어 삭제해준다.

그다음 리스트의 state 와 asyncstorage 를 갱신시키고 다시 load 해준다.

 

Alert API를 사용하여 커스텀 confirm 창을 만들어줘서 삭제 안내문구도 넣어줬다.

 

const removeTodos = async (key) => {
    try {
      Alert.alert('삭제 안내', '정말로 삭제하시겠습니까?', [
        {
          text: 'Cancel',
          onPress: () => { return },
          style: 'cancel',
        },
        { 
          text: 'OK', 
          onPress: async () => {
            Reflect.deleteProperty(todos, key);
            await saveTodos(todos);
            loadTodos();
          }
        }
      ]);
    } catch(err) {
      throw err;
    }
  }

오늘은 여기까지!