๐Ÿ’ป[React Native] Expo๋กœ TodoList ๋งŒ๋“ค๊ธฐ5-AsyncStorage

ํ˜ฑยท2023๋…„ 1์›” 15์ผ

๐Ÿ“Œ AsyncStorage

list์— ๋Œ€ํ•œ ๋ถ€๋ถ„๋“ค์„ ์ €์žฅํ•  ์ˆ˜ ์žˆ๋„๋ก ํ•˜๋Š” ๊ธฐ๋Šฅ
expo install @react-native-async-storage/async-storage
๋น„๋™๊ธฐ๋กœ ๋™์ž‘, key+value(๋‘˜๋‹ค string! ๋ณ€ํ•œํ•ด์•ผ ํ•จ)๋กœ ๊ตฌ์„ฑ๋œ ๋‹จ์ˆœ storage
key, value๋กœ ๋™์ž‘ํ•˜๋ฏ€๋กœ ํ•œ api๋กœ ํ˜ธ์ถœ์ด ๊ฐ€๋Šฅ

//์ž…๋ ฅ ์ฒ˜๋ฆฌ
 const addItem = useCallback(() => {
    const newData = [
      ...list,
      { key: new Date().toString(), content: inputText },
    ]; 
   //์ž…๋ ฅํ•œ ๋ฐ์ดํ„ฐ๋ฅผ ์›๋ž˜ list ์•ˆ์˜ ๊ฐ’๊ณผ ํ•จ๊ป˜ key, content ๊ฐ’์œผ๋กœ ๋‚˜ํƒ€๋ƒ„
    setList(newData);
   //์ž…๋ ฅํ•œ ๋ฐ์ดํ„ฐ๋ฅผ setList์— ํฌํ•จ
    AsyncStorage.setItem("todo-list", JSON.stringify(newData));
   //AsnycStorage์— todo-list๋ผ๋Š” key์™€ newData๋ผ๋Š” value๋ฅผ stringํ™”ํ•ด์„œ ์ €์žฅ
   setInputText("")
  }, [list, inputText]);
//AstncStorage ์•ˆ์˜ data๋ฅผ ๋ถˆ๋Ÿฌ์˜ด (getItem)
 useEffect(() => {
    AsyncStorage.getItem("todo-list").then((rawData) => {
      if (rawData) {
        setList(JSON.parse(rawData));
      } else {
        setList([]);
      }
    });
  }, []);
//์‚ญ์ œ ์ฒ˜๋ฆฌ
const removeItem = useCallback(
    (key) => {
      const newData = list.filter((item) => item.key !== key);
      setList(newData); //์‚ญ์ œ ํ›„ Stroage์— ๋„ฃ์–ด์คŒ
      AsyncStorage.setItem("todo-list", JSON.stringify(newData));
    },
    [list]
  );

๊ฒน์น˜๋Š” ๋ถ€๋ถ„ function์œผ๋กœ ๋ฌถ์–ด์„œ ๊ฐ„๋‹จํ•˜๊ฒŒ ์ฒ˜๋ฆฌ

function updateStorage(data) {
  return AsyncStorage.setItem("todo-list", JSON.stringify(newData));
}

export default function App() {
  const [list, setList] = useState([]);
  const [inputText, setInputText] = useState("");
  const addItem = useCallback(() => {
    const newData = [
      ...list,
      { key: new Date().toString(), content: inputText },
    ];
    setList(newData);
    updateStorage(newData);
    setInputText("");
  }, [list, inputText]);

  const removeItem = useCallback(
    (key) => {
      const newData = list.filter((item) => item.key !== key);
      setList(newData);
      updateStorage(newData);
    },
    [list]
  );

  useEffect(() => {
    AsyncStorage.getItem("todo-list").then((rawData) => {
      if (rawData) {
        setList(JSON.parse(rawData));
      } else {
        setList([]);
      }
    });
  }, []);

โšก๏ธ ์™„๋ฃŒ์— ๋Œ€ํ•œ ์ƒํƒœ๋ฅผ ํšจ์œจ์ ์œผ๋กœ ์–ด๋–ป๊ฒŒ ๊ด€๋ฆฌํ•˜๋Š”๊ฐ€?

๐Ÿ“Œ React ๋ถˆ๋ณ€์„ฑ (immutable)

์›๋ณธ์„ ๋ณ€๊ฒฝํ•˜์ง€ ์•Š๋Š”๋‹ค, ๋ฐ˜๋“œ์‹œ ๋ณ€๊ฒฝ๋œ ์‚ฌ๋ณธ์„ ํ†ตํ•ด ๋น„๊ตํ•œ๋‹ค
๋ฌด์—‡์ด ๋ณ€๊ฒฝ๋˜์—ˆ๋Š” ์ง€๋ฅผ ํ†ตํ•ด ๋ณ€๊ฒฝ๋œ ๋ถ€๋ถ„์„ ์ฐพ์•„๋‚ธ๋‹ค
array.filter: ์›๋ณธ์€ ๋ณ€๊ฒฝ๋˜์ง€ ์•Š์Œ, ์‚ฌ๋ณธ์„ ์ƒ์„ฑ, ์ถ”๋ ค๋‚ด์–ด ๋น„๊ต
array.push(): ์›๋ณธ์„ ๋ณ€๊ฒฝํ•จ

immer

js์˜ ๊ธฐ๋ณธ state๋ฅผ ๋‹ค๋ฃจ๋Š” ๊ฒƒ
draft: ๋ณ€๊ฒฝ์„ ์–ผ๋งˆ๋“ ์ง€ ํ•  ์ˆ˜ ์žˆ๋Š” ์ดˆ์•ˆ

//App.js
import produce from "immer";

const updateItem = useCallback((key, value) => {
      const newData = produce(list, (draft) => {
        const index = list.findIndex((item) => item.key === key);
        draft[index].isDone = value;
      });
      setList(newData);
      updateStorage(newData);
    },
    [list]
  );

   <TodoItem
              id={item.item.key}
              label={item.item.content}
              isDone={item.item.isDone}
              onSwitchChange={updateItem}
              onDelete={() => removeItem(item.item.key)}
            />
          )}
          style={{ flex: 1 }}
        />

//TodoItem.js
export default function TodoItem({ label, onDelete,
isDone, onSwitchChange }) {

  return (
    <Row style={{ alignItems: "center", marginBottom: 12 }}>
      <Switch
        value={isDone}
        onValueChange={(value) => onSwitchChange(id, value)}
        valuestyle={{ marginRight: 8 }}
      />
      <Text style={{ color: isDone ? "#eee" : "#000" }}>
        {label ?? "๋‚ด์šฉ ์—†์Œ"}
      </Text>
      <Button title="์‚ญ์ œ" onPress={onDelete} />
    </Row>
  );
}

switch ๋ณ€๊ฒฝ์ด ๋˜์–ด๋„ ๋ณ€๊ฒฝ๋œ ๋‚ด์šฉ์ด storage์— ์ž˜ update๋จ
array, object ๋“ฑ์ด ๋“ค์–ด๊ฐ€๋ฉด ์ƒํƒœ๋ฅผ ๊ด€๋ฆฌํ•˜๋Š” ๊ฒƒ์— ๋Œ€ํ•œ ๋„์ž…์ด ํ•„์š”

profile
new blog: https://hae0-02ni.tistory.com/

0๊ฐœ์˜ ๋Œ“๊ธ€