2020/03/10
Context API를 이용하여 todoList App을 만들어보려고 합니다. 할 일을 입력하게 되면, AsyncStorage에 데이터를 저장하려고 합니다.
interface ITodoListContext {
todoList: Array<string>; // todoList는 string인 array
addTodoList: (todo: string) => void;
// addToList는 string인 todo를 인자로 받는 함수
removeTodoList: (index: number) => void;
// addToList는 number인 index를 인자로 받는 함수
}
import React, { createContext, useState, useEffect } from 'react';
import AsyncStorage from '@react-native-community/async-storage';
interface Props {
children: JSX.Element | Array<JSX.Element>;
}
const TodoListContext =
createContext <
ITodoListContext >
{
todoList: [],
addTodoList: (todo: string): void => {},
removeTodoList: (index: number): void => {},
};
const TodoListContextProvider = ({ children }: Props) => {
const [todoList, setTodoList] = useState < Array < string >> [];
const addTodoList = (todo: string): void => {
const list = [...todoList, todo];
setTodoList(list);
AsyncStorage.setItem('todoList', JSON.stringify(list));
};
// 할 일을 추가하는 함수
// 기존의 todoList를 ...todoList하여 복사한 후, 인자로 받은 todo를 추가해준다.
// AsyncStorage에 JSON.stringfy()를 사용하여 문자열로 변경한 후에 todoList라는 key값으로 list를 저장한다.
const removeTodoList = (index: number): void => {
let list = [...todoList];
list.splice(index, 1);
setTodoList(list);
AsyncStorage.setItem('todoList', JSON.stringify(list));
};
// 할 일을 삭제하는 함수
// 기존의 배열인 todoList를 ...todoList하여 복사한 후, splice를 통해 삭제한다.
// setTodoList(list)를 통해 todoList의 상태를 업데이트 해준 후, AsycStorage도 업데이트 한다.
const initData = async () => {
try {
const list = await AsyncStorage.getItem('todoList');
if (list !== null) {
setTodoList(JSON.parse(list));
}
} catch (e) {
console.log(e);
}
};
// App이 실행될 때, AsyncStorage에서 todoList를 가져온다. async/await을 사용하여 비동기처리를 한다.
useEffect(() => {
initData();
}, []);
// componentDidMount와 같이 useEffect를 사용하여, 랜더링 후 실행하도록 한다.
return (
<TodoListContext.Provider
value={{
todoList,
addTodoList,
removeTodoList,
}}
>
{children}
</TodoListContext.Provider>
);
};
// props로 전역 상태를 전달해 준다.
export { TodoListContextProvider, TodoListContext };
import React from 'react';
import styled from 'styled-components/native';
import { TodoListContextProvider } from '~/context/TodoListContext';
import Todo from './screens/Todo';
const App = () => {
return (
<TodoListContextProvider>
<Container>
<Todo />
</Container>
</TodoListContextProvider>
);
};
export default App;
import React, { useContext } from 'react';
import { FlatList } from 'react-native';
import styled from 'styled-components/native';
import { TodoListContext } from '~/context/TodoListContext';
import EmptyItem from './EmptyItem';
import TodoItem from './TodoItem';
interface Props {}
const TodoList = ({ }: Props) => {
const { todoList, removeTodoList } = useContext<ITodoListContext>(
TodoListContext
);
// TodoListContext 안에서 사용하고자 하는 todoList와 removeTodoList를 불러와 사용한다.
return (
<Container
data={todoList}
keyExtractor={(item, index) => {
return `todo-${index}`;
}}
ListEmptyComponent={<EmptyItem />}
renderItem={({ item, index }) => (
<TodoItem
text={item as string}
onDelete={() => removeTodoList(index)}
/>
)}
contentContainerStyle={todoList.length === 0 && { flex: 1 }}
/>
);
};
export default TodoList;
const Container = styled(FlatList)``;
// FlatList component는 밑에서 알아보도록 하겠다.
FlatList components는 심플한 api, 높은 퍼포먼스, 편리한 기능지원을 하는 리스트 컴포넌트
todoList.length === 0 && {flex: 1}
ListEmptyComponent 친구의 스타일을 정의