An open API service indexing awesome lists of open source software.

https://github.com/ssi02014/react-native-todoapp

๐Ÿ“ฑ ๋ฆฌ์•กํŠธ ๋„ค์ดํ‹ฐ๋ธŒ ToDoList App
https://github.com/ssi02014/react-native-todoapp

Last synced: 19 days ago
JSON representation

๐Ÿ“ฑ ๋ฆฌ์•กํŠธ ๋„ค์ดํ‹ฐ๋ธŒ ToDoList App

Awesome Lists containing this project

README

          

# ๐Ÿ’ป React-Native-TodoApp
### React-Native-TodoApp ์ €์žฅ์†Œ


## ๐ŸŽฅ App View




## ๐Ÿ‘จ๐Ÿปโ€๐Ÿ’ป ๊ธฐ์ˆ  ์Šคํ…
1. React-Native
2. Styled-Components - styling
3. AsyncStorage
4. Google Material Design - icon




## ๐Ÿ‘จ๐Ÿปโ€๐Ÿ’ป SafeAreaView, StatusBar Component
- SafeAreaView๋Š” ์•„์ดํฐ11๊ณผ ๊ฐ™์€ ๋…ธ์น˜ ๋””์ž์ธ๋•Œ๋ฌธ์— ๊ฐ€๋ ค์ง€๋Š” ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•ด ์ฃผ๋Š” ์ปดํฌ๋„ŒํŠธ์ด๋‹ค.
- StatusBar๋Š” ์•ˆ๋“œ๋กœ์ด๋“œ Title ์ปดํฌ๋„ŒํŠธ๊ฐ€ ์ƒํƒœ ๋ฐ”(Status Bar)์— ๊ฐ€๋ ค์ง€๋Š” ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•ด์ฃผ๋Š” ์ปดํฌ๋„ŒํŠธ์ด๋‹ค.
- StatusBar์—์„œ barStyle์„ ํ†ตํ•ด ์ƒํƒœ ๋ฐ”์˜ ๋‚ด์šฉ์˜ ์ƒ‰์„ ์ˆ˜์ •ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
- StatusBar์—์„œ backgroundColor๋Š” ์•ˆ๋“œ๋กœ์ด๋“œ์—์„œ๋งŒ ์ ์šฉ๋˜๋Š” ์†์„ฑ์ด๋ฉฐ ์ƒํƒœ ๋ฐ”์˜ ๋ฐ”ํƒ•์ƒ‰์„ ์ˆ˜์ •ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

```javascript
//SageAreaView
const Container = styled.SafeAreaView`
(...)
`;
```

```javascript
//StatusBar
import { StatusBar } from 'react-native';

```


## ๐Ÿ‘จ๐Ÿปโ€๐Ÿ’ป Dimensions, useWindowDimensions
- Dimensions, useWindowDimensions ๋ชจ๋‘ ํ˜„์žฌ ๊ธฐ๊ธฐ์˜ ํ™”๋ฉด ํฌ๊ธฐ๋ฅผ ์•Œ ์ˆ˜ ์žˆ๊ณ , ์ด๋ฅผ ์ด์šฉํ•ด ๋‹ค์–‘ํ•œ ํฌ๊ธฐ์˜ ๊ธฐ๊ธฐ์— ๋™์ผํ•œ ๋ชจ์Šต์œผ๋กœ ์ ์šฉ๋  ์ˆ˜ ์žˆ๋„๋ก ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑํ•  ์ˆ˜ ์žˆ๋‹ค.
- Dimensions๋Š” ์ฒ˜์Œ ๊ฐ’์„ ๋ฐ›์•„์™”์„ ๋•Œ์˜ ํฌ๊ธฐ๋กœ ๊ณ ์ •๋˜๊ธฐ ๋•Œ๋ฌธ์— ๊ธฐ๊ธฐ๋ฅผ ํšŒ์ „ํ•ด์„œ ํ™”๋ฉด์ด ์ „ํ™˜๋˜๋ฉด ๋ณ€ํ™”๋œ ํ™”๋ฉด์˜ ํฌ๊ธฐ๊ฐ€ ์ผ์น˜ํ•˜์ง€ ์•Š๋Š” ๋ฌธ์ œ๊ฐ€ ์žˆ๋‹ค.
- useWindowDimensions๋Š” ๋ฆฌ์•กํŠธ ๋„ค์ดํ‹ฐ๋ธŒ์—์„œ ์ œ๊ณตํ•˜๋Š” Hooks์ค‘ ํ•˜๋‚˜๋กœ, ํ™”๋ฉด์˜ ํฌ๊ธฐ๊ฐ€ ๋ณ€๊ฒฝ๋˜๋ฉด ํ™”๋ฉด์˜ ํฌ๊ธฐ, ๋„ˆ๋น„ ,๋†’์ด๋ฅผ ์ž๋™์œผ๋กœ ์—…๋ฐ์ดํŠธํ•œ๋‹ค.

![1](https://user-images.githubusercontent.com/64779472/113824104-5888be80-97ba-11eb-88dc-2b4f1c41bd9f.PNG)

```javascript
//Dimensions
import { Dimensions } from 'react-native';

const Input = () => {
const width = Dimensions.get('window').width;

return
}
```

```javascript
//useWindowDimensions
import { useWindowDimensions } from 'react-native';

const Input = () => {
const width = useWindowDimensions().width;

return
}
```


## ๐Ÿ‘จ๐Ÿปโ€๐Ÿ’ป TextInput ์†์„ฑ
- autoCapitalize: ์ž๋™์œผ๋กœ ๋Œ€๋ฌธ์ž ์ „ํ™˜(iOS)
- autoCorrect: ์ž๋™ ์ˆ˜์ • ๊ธฐ๋Šฅ(iOS)
- returnKeyType: ํ‚ค๋ณด๋“œ์˜ ์™„๋ฃŒ ๋ฒ„ํŠผ ์„ค์ •(iOS)
- keyboardApperance: ํ‚ค๋ณด๋“œ ์ƒ‰ ์„ค์ •(iOS)

```javascript

```

## ๐Ÿ‘จ๐Ÿปโ€๐Ÿ’ป Google Material Design
๐Ÿ”– https://material.io/resources/icons/?style=baseline

![2](https://user-images.githubusercontent.com/64779472/113828270-2b8ada80-97bf-11eb-8341-724f9b55296f.PNG)

- ํ”„๋กœ์ ํŠธ์— ์‚ฌ์šฉํ•  ์•„์ด์ฝ˜ ์ด๋ฏธ์ง€๋ฅผ ๋‹ค์šด๋ฐ›์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
- iOS๋กœ ๋‹ค์šด๋ฐ›์œผ๋ฉด x2, x3 ์‚ฌ์ด์ง€์˜ ์•„์ด์ฝ˜์ด ํ•จ๊ป˜ ์žˆ์Šต๋‹ˆ๋‹ค.
- ํŒŒ์ผ๋ช…์„ ๋™์ผํ•œ ์ด๋ฆ„์„ ์‚ฌ์šฉํ•˜๋ฉด์„œ @2x, @3x๋ฅผ ๋ถ™์ด๋ฉด ๋ฆฌ์•กํŠธ ๋„ค์ดํ‹ฐ๋ธŒ์—์„œ ํ™”๋ฉด ์‚ฌ์ด์ฆˆ์— ์•Œ๋งž์€ ํฌ๊ธฐ์˜ ์ด๋ฏธ์ง€๋ฅผ ์ž๋™์œผ๋กœ ๋ถˆ๋Ÿฌ์™€ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.


## ๐Ÿ‘จ๐Ÿปโ€๐Ÿ’ป Image, IconButton Component
- Image Component๋Š” ๋ฆฌ์•กํŠธ ๋„ค์ดํ‹ฐ๋ธŒ์—์„œ ์ œ๊ณตํ•˜๋Š” ์ปดํฌ๋„ŒํŠธ์ด๋ฉฐ, ํ”„๋กœ์ ํŠธ์— ์žˆ๋Š” ์ด๋ฏธ์ง€ ํŒŒ์ผ์˜ ๊ฒฝ๋กœ๋‚˜ URL์„ ์ด์šฉํ•˜์—ฌ ์›๊ฒฉ์— ์žˆ๋Š” ์ด๋ฏธ์ง€๋ฅผ ๋ Œ๋”๋งํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
- tint-color๋ฅผ ํ†ตํ•ด ์•„์ด์ฝ˜์— ์ƒ‰๊น”์„ ์ค„ ์ˆ˜ ์žˆ๋‹ค.

```javascript
const Icon = styled.Image`
tint-color: ${({theme}) => theme.text};
width: 30px;
height: 30px;
margin: 10px;
`;

const IconButton = ({ type, onPressOut }) => {
return (



);
};

IconButton.propTypes = {
// PropTypes.oneOf: ์—ด๊ฑฐํ˜•(enum)์œผ๋กœ ์ฒ˜๋ฆฌํ•˜์—ฌ prop๊ฐ€ ํŠน์ • ๊ฐ’๋“ค๋กœ ์ œํ•œ๋˜๋„๋ก ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
type: PropTypes.oneOf(Object.values(images)).isRequired,
onPressOut: PropTypes.func,
}
```


## ๐Ÿ‘จ๐Ÿปโ€๐Ÿ’ป ThemeProvider
- ๋ชจ๋“  ์ปดํฌ๋„ŒํŠธ๋ฅผ ๊ฐ์‹ธ๋Š” ์ตœ์ƒ์œ„ ์ปดํฌ๋„ŒํŠธ๋กœ ThemeProvider ์ปดํฌ๋„ŒํŠธ๋ฅผ ์‚ฌ์šฉํ•˜๋ฉฐ, ThemeProvider ์ปดํฌ๋„ŒํŠธ์˜ theme ์†์„ฑ์— ์•ž์—์„œ ์ •์˜ํ•œ ์ƒ‰์„ ์„ค์ •ํ•˜๋ฉด, ThemeProvider ์ปดํฌ๋„ŒํŠธ์˜ ์ž์‹ ์ปดํฌ๋„ŒํŠธ์—์„œ๋Š” ์Šคํƒ€์ผ๋“œ ์ปดํฌ๋„ŒํŠธ๋ฅผ ์ด์šฉํ•  ๋•Œ, props๋กœ theme๋ฅผ ์ „๋‹ฌ๋ฐ›์•„ ์ด์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.

```javascript


(...)


```


## ๐Ÿ‘จ๐Ÿปโ€๐Ÿ’ป CRUD ๋ฉ”์„œ๋“œ ๊ตฌํ˜„
### ๐Ÿƒ _addTask
```javascript
const _addTask = () => {
const ID = Date.now().toString();
const newTaskObject = {
[ID]: { id: ID, text: newTask, completed: false},
}
alert(`Add: ${newTask}`);
setNewTask('');
setTasks({...tasks, ...newTaskObject});
};
```


### ๐Ÿƒ _deleteTask
```javascript
const _deleteTask = id => {
// Object.assign ๋ฉ”์†Œ๋“œ๋Š” ์—ด๊ฑฐํ•  ์ˆ˜ ์žˆ๋Š” ํ•˜๋‚˜ ์ด์ƒ์˜ ์ถœ์ฒ˜ ๊ฐ์ฒด๋กœ๋ถ€ํ„ฐ ๋Œ€์ƒ ๊ฐ์ฒด๋กœ ์†์„ฑ์„ ๋ณต์‚ฌํ•  ๋•Œ ์‚ฌ์šฉ
const currentTasks = Object.assign({}, tasks);
delete currentTasks[id];
setTasks(currentTasks);
};
```


### ๐Ÿƒ _toggleTask
```javascript
const _toggleTask = id => {
const currentTasks = Object.assign({}, tasks);
currentTasks[id]['completed'] = !currentTasks[id]['completed'];
setTasks(currentTasks);
};
```


### ๐Ÿƒ _updateTask
```javascript
const _updateTask = item => {
const currentTasks = Object.assign({}, tasks);
currentTasks[item.id] = item;
setTasks(currentTasks);
}
```


## ๐Ÿ‘จ๐Ÿปโ€๐Ÿ’ป ๋ถ€๊ฐ€ ๊ธฐ๋Šฅ
### ๐Ÿƒ AsyncStorage
- ๋ฆฌ์•กํŠธ ๋„ค์ดํ‹ฐ๋ธŒ์—์„œ๋Š” AsyncStorage๋ฅผ ์ด์šฉํ•ด ๋กœ์ปฌ์— ๋ฐ์ดํ„ฐ๋ฅผ ์ €์žฅํ•˜๊ณ  ๋ถˆ๋Ÿฌ์˜ค๋Š” ๊ธฐ๋Šฅ์„ ๊ตฌํ˜„ํ•  ์ˆ˜ ์žˆ๋‹ค.
- AsyncStorage๋Š” ๋น„๋™๊ธฐ๋กœ ๋™์ž‘ํ•˜๋ฉฐ ๋ฌธ์ž์—ด๋กœ ๋œ ํ‚ค-๊ฐ’(Key-Value) ํ˜•ํƒœ์˜ ๋ฐ์ดํ„ฐ๋ฅผ ๊ธฐ๊ธฐ์— ์ €์žฅํ•˜๊ณ  ๋ถˆ๋Ÿฌ์˜ฌ ์ˆ˜ ์žˆ๋Š” ๊ธฐ๋Šฅ์„ ์ œ๊ณตํ•œ๋‹ค.
- expo install์€ npm install๊ณผ ๊ฑฐ์˜ ๋™์ผํ•œ ์—ญํ• ์„ ํ•œ๋‹ค. ์ฐจ์ด์ ์€ ์‚ฌ์šฉ์ค‘์ธ Expo SDK ๋ฒ„์ „๊ณผ ํ˜ธํ™˜๋˜๋Š” ๋ฒ„์ „์ด ์žˆ๋Š”์ง€ ํ™•์ธํ•˜๊ณ , ํ•ด๋‹น ๋ฒ„์ „์˜ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ์„ค์น˜ํ•˜๋Š” ๊ณผ์ •์ด ์ถ”๊ฐ€๋˜์—ˆ๋‹ค.

```javascript
//intall ์ˆ˜์ • ์ „
expo install @react-native-community/async-storage

//install ์ˆ˜์ • ํ›„
expo install @react-native-async-storage/async-storage

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

//๋ฐ์ดํ„ฐ ๋‹ด๊ธฐ
const _saveTasks = async tasks => {
try {
await AsyncStorage.setItem('tasks', JSON.stringify(tasks));
setTasks(tasks);
} catch (e) {
console.error(e);
}
}

//๋ฐ์ดํ„ฐ ๋ถˆ๋Ÿฌ์˜ค๊ธฐ
const _loadTasks = async () => {
const loadedTasks = await AsyncStorage.getItem('tasks');
setTasks(JSON.parse(loadedTasks || {}));
};
```


### ๐Ÿƒ AppLoading
- AppLoading ์ปดํฌ๋„ŒํŠธ๋Š” ํŠน์ • ์กฐ๊ฑด์—์„œ ๋กœ๋”ฉ ํ™”๋ฉด์ด ์œ ์ง€๋˜๋„๋ก ํ•˜๋Š” ๊ธฐ๋Šฅ์œผ๋กœ, ๋ Œ๋”๋ง ํ•˜๊ธฐ ์ „์— ์ฒ˜๋ฆฌํ•ด์•ผ ํ•˜๋Š” ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•˜๋Š” ๋ฐ ์œ ์šฉํ•˜๊ฒŒ ์‚ฌ์šฉ๋œ๋‹ค.
1. startAsync: AppLoading ์ปดํฌ๋„ŒํŠธ๊ฐ€ ๋™์ž‘ํ•˜๋Š” ๋™์•ˆ ์‹คํ–‰ ๋  ํ•จ์ˆ˜
2. onFinish: startAsync๊ฐ€ ์™„๋ฃŒ๋˜๋ฉด ์‹คํ–‰ํ•  ํ•จ์ˆ˜
3. onError: startAsync์—์„œ ์˜ค๋ฅ˜๊ฐ€ ๋ฐœ์ƒํ•˜๋ฉด ์‹คํ–‰ํ•  ํ•จ์ˆ˜

```javascript
//install
expo install expo-app-loading

//import
import AppLoading from 'expo-app-loading';

//AppLoading ์˜ˆ์‹œ
setIsReady(true)}
onError={console.error}
/>
```


### ๐Ÿƒ app.json
- ๋กœ๋”ฉ ํ™”๋ฉด, ์•„์ด์ฝ˜์„ app.json์—์„œ ๋ฐ”๊ฟ€ ์ˆ˜ ์žˆ๋‹ค.
- ๋กœ๋”ฉ ํ™”๋ฉด์œผ๋กœ ์‚ฌ์šฉ ๋  ์ด๋ฏธ์ง€์˜ ํฌ๊ธฐ๋Š” ๋‹ค์–‘ํ•œ ๊ธฐ๊ธฐ์— ๋Œ€์‘ํ•˜๊ธฐ ์œ„ํ•ด 1242 x 2436์œผ๋กœ ์ค€๋น„ํ•˜๋Š” ๊ฒƒ์ด ์ข‹๋‹ค.
- ๋กœ๋”ฉ ํ™”๋ฉด์—์„œ ๊ธฐ๊ธฐ์˜ ํฌ๊ธฐ์— ๋”ฐ๋ผ ๊ณต๋ฐฑ์ด ์ƒ๊ธฐ๋Š” ๊ฒฝ์šฐ, resizeMode์˜ ๊ฐ’์„ cover๋กœ ๋ณ€๊ฒฝํ•˜๊ฑฐ๋‚˜, backgroundColor์˜ ๊ฐ’์„ ๋ณ€๊ฒฝํ•˜๋ฉด ๋œ๋‹ค.
- ์•„์ด์ฝ˜์œผ๋กœ ์‚ฌ์šฉ ๋  ์ด๋ฏธ์ง€๋Š” iOS์˜ ๊ฒฝ์šฐ 1024 x 1024 ํฌ๊ธฐ๊ฐ€ ํ•„์š”ํ•˜๊ณ  ์•ˆ๋“œ๋กœ์ด๋“œ์˜ ๊ฒฝ์šฐ 512 x 512ํฌ๊ธฐ์˜ ์ด๋ฏธ์ง€๊ฐ€ ํ•„์š”ํ•˜๋ฏ€๋กœ, ์›ฌ๋งŒํ•˜๋ฉด 1024 x 1024 ํฌ๊ธฐ์˜ ์ด๋ฏธ์ง€๋ฅผ ์‚ฌ์šฉํ•˜๋Š”๊ฒŒ ์ข‹๋‹ค.

```json
{
"expo": {
//(...์ƒ๋žต)
"icon": "./assets/splash.png",
"splash": {
"image": "./assets/splash.png",
"resizeMode": "contain",
"backgroundColor": "#ffffff"
},
//(...์ƒ๋žต)
"android": {
"adaptiveIcon": {
"foregroundImage": "./assets/splash.png",
"backgroundColor": "#FFFFFF"
}
},
//(...์ƒ๋žต)
}
}
```