๐ŸŽ‰ berenickt ๋ธ”๋กœ๊ทธ์— ์˜จ ๊ฑธ ํ™˜์˜ํ•ฉ๋‹ˆ๋‹ค. ๐ŸŽ‰
Mobile
React Native
02-Core Component

1. View and Components

1.1 View

react-native์ž์ฃผ์“ฐ๋Š” core components

  • ์œ„ ๊ทธ๋ฆผ์€ ๊ฐ๊ฐ Android์™€ iOS์—์„œ ํ™”๋ฉด์„ ๊ทธ๋ฆด ๋–„, ์“ฐ๋Š” ์ปดํฌ๋„ŒํŠธ๋“ค์„ ๋ณด์—ฌ์ค€๋‹ค.

  • ๋ฆฌ์ŠคํŠธ๋“ค ์ค‘์—์„œ ํ•˜๋‚˜์˜ ์•„์ดํ…œ์„ ํ‘œํ˜„ํ•  ๋–„,

    • Android๋Š” ViewGroup์œผ๋กœ ๊ฐ์‹ธ๊ณ , ๊ทธ ์•ˆ์ชฝ ์•„์ด์ฝ˜์€ ImageView, ๊ธ€์ž๋Š” TextView ์ปดํฌ๋„ŒํŠธ๋ฅผ ์‚ฌ์šฉ
    • iOS๋Š” UIView์œผ๋กœ ๊ฐ์‹ธ๊ณ , ๊ทธ ์•ˆ์ชฝ ์•„์ด์ฝ˜์€ UIImageView, ๊ธ€์ž๋Š” UITextView ์ปดํฌ๋„ŒํŠธ๋ฅผ ์‚ฌ์šฉ
  • ๊ทธ๋Ÿฌ๋ฉด React Native์—์„œ๋Š” ๊ฐ OS๋ณ„ ์ปดํฌ๋„ŒํŠธ๋“ค์„ ์–ด๋–ค ๊ฑธ๋กœ ๋Œ€์ฒดํ•ด์•ผ ํ• ๊นŒ?

    • ๋ฐ”๋กœ Native Component์ด๋‹ค.
  • cf. https://reactnative.dev/docs/intro-react-native-components


1.2 Native Component

Native Components: ํ”Œ๋žซํผ(iOS ๋˜๋Š” Android)์˜ view๋ฅผ JS๋กœ ํ˜ธ์ถœํ•  ์ˆ˜ ์žˆ๊ฒŒ ํ•ด์ฃผ๋Š” React ์ปดํฌ๋„ŒํŠธ

  • ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑํ•  ๋•, JavaScript์™€ React Component
  • Runtime์—์„œ React Native๊ฐ€ ๊ตฌํ˜„ํ•œ ์ฝ”๋“œ์— ์ƒ์‘ํ•˜๋Š” ์•ˆ๋“œ๋กœ์ด๋“œ์™€ iOS view๋ฅผ ์ƒ์„ฑํ•จ
  • ๋‹ค๋ฅธ ์‚ฌ๋žŒ์ด ๋งŒ๋“  Native Component๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜๋„ ์žˆ์Œ: React Native Directory

1.3 ๋Œ€ํ‘œ์ ์ธ Core Components

REACT NATIVE UI COMPONENTANDROID VIEWIOS VIEWWEB ANALOGDESCRIPTION
<View><ViewGroup><UIView>A non-scrolling <div>flexbox, ์Šคํƒ€์ผ, ์ผ๋ถ€ ํ„ฐ์น˜ ์ฒ˜๋ฆฌ, ์ ‘๊ทผ์„ฑ ์ปจํŠธ๋กค์„ ์ง€์›ํ•˜๋Š” ์ปจํ…Œ์ด๋„ˆ
<Text><TextView><UITextView><p>ํ…์ŠคํŠธ ๋ฌธ์ž์—ด์„ ํ‘œ์‹œ, ์Šคํƒ€์ผ๋งํ•˜๊ณ  ์ค‘์ฒฉํ•˜๋ฉฐ, ์‹ฌ์ง€์–ด ํ„ฐ์น˜ ์ด๋ฒคํŠธ๋ฅผ ์ฒ˜๋ฆฌ
<Image><ImageView><UIImageView><img>๋‹ค์–‘ํ•œ ์œ ํ˜•์˜ ์ด๋ฏธ์ง€๋ฅผ ํ‘œ์‹œ
<ScrollView><ScrollView><UIScrollView><div>์—ฌ๋Ÿฌ ์ปดํฌ๋„ŒํŠธ์™€ ๋ทฐ๋ฅผ ํฌํ•จํ•  ์ˆ˜ ์žˆ๋Š” ์ผ๋ฐ˜ ์Šคํฌ๋กค ์ปจํ…Œ์ด๋„ˆ
<TextInput><EditText><UITextField><input type="text">์‚ฌ์šฉ์ž๊ฐ€ ํ…์ŠคํŠธ๋ฅผ ์ž…๋ ฅํ•  ์ˆ˜ ์žˆ๊ฒŒ ํ•จ
  • Core Components : React Native๊ฐ€ ๊ธฐ๋ณธ์ ์œผ๋กœ ์ œ๊ณตํ•˜๋Š” Native Components ์„ธํŠธ
  • ๊ทธ ์™ธ ๋ชจ๋“  Core Component๋Š” ๊ณต์‹ ๋ฌธ์„œ Core Components and APIs ยท React Native๋ฅผ ํ™•์ธ

2. Core Components ์˜ˆ์‹œ

2.1 Text Input

  • <TextInput> : html์—์„œ์˜ <input type="text"> ์™€ ๋™์ผ
  • ์œ ์ €์˜ ํ…์ŠคํŠธ ์ž…๋ ฅ์„ ๋ฐ›์„ ์ˆ˜ ์žˆ๋Š” ์ปดํฌ๋„ŒํŠธ
  • cf. https://reactnative.dev/docs/next/handling-text-input
1
import React, { useState } from 'react'
2
import { Text, TextInput, View } from 'react-native'
3
4
const PizzaTranslator = () => {
5
const [text, setText] = useState('')
6
7
return (
8
<View style={{ padding: 100 }}>
9
<TextInput
10
style={{ height: 40 }}
11
placeholder="Type here to translate!"
12
onChangeText={newText => setText(newText)}
13
defaultValue={text}
14
/>
15
<Text style={{ padding: 10, fontSize: 42 }}>
16
{text
17
.split(' ')
18
.map(word => word && '๐Ÿ•')
19
.join(' ')}
20
</Text>
21
</View>
22
)
23
}
24
25
export default PizzaTranslator

2.2 Scroll View

  • View๋Š” 2๊ฐ€์ง€ ์ข…๋ฅ˜๊ฐ€ ์žˆ๋‹ค.
    1. <View>: ์Šคํฌ๋กค์ด ๋ถˆ๊ฐ€๋Šฅํ•œ <div>
    2. <ScrollView>: ์Šคํฌ๋กค ๊ฐ€๋Šฅํ•œ <div>
  • ์Šคํฌ๋กค ๊ฐ€๋Šฅํ•œ ์ปจํ…Œ์ด๋„ˆ๋ฅผ ๋งŒ๋“œ๋ ค๋ฉด <ScrollView>๋ฅผ ์‚ฌ์šฉํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.
  • cf. https://reactnative.dev/docs/next/using-a-scrollview
1
import React from 'react'
2
import { Image, ScrollView, Text } from 'react-native'
3
4
const logo = {
5
uri: 'https://reactnative.dev/img/tiny_logo.png',
6
width: 64,
7
height: 64,
8
}
9
10
const App = () => (
11
<ScrollView>
12
<Text style={{ fontSize: 96 }}>Scroll me plz</Text>
13
<Image source={logo} />
14
<Image source={logo} />
15
<Image source={logo} />
16
<Image source={logo} />
17
<Image source={logo} />
18
<Text style={{ fontSize: 96 }}>If you like</Text>
19
<Image source={logo} />
20
<Image source={logo} />
21
<Image source={logo} />
22
<Image source={logo} />
23
<Image source={logo} />
24
<Text style={{ fontSize: 96 }}>Scrolling down</Text>
25
<Image source={logo} />
26
<Image source={logo} />
27
<Image source={logo} />
28
<Image source={logo} />
29
<Image source={logo} />
30
<Text style={{ fontSize: 96 }}>What's the best</Text>
31
<Image source={logo} />
32
<Image source={logo} />
33
<Image source={logo} />
34
<Image source={logo} />
35
<Image source={logo} />
36
<Text style={{ fontSize: 96 }}>Framework around?</Text>
37
<Image source={logo} />
38
<Image source={logo} />
39
<Image source={logo} />
40
<Image source={logo} />
41
<Image source={logo} />
42
<Text style={{ fontSize: 80 }}>React Native</Text>
43
</ScrollView>
44
)
45
46
export default App

iOS์˜ ๊ฒฝ์šฐ, ScrollView์—์„œ ์คŒ์ด ๊ฐ€๋Šฅํ•˜๊ฒŒ ํ•  ์ˆ˜ ์žˆ์Œ

  • maximumZoomScale: ์ตœ๋Œ€ ์คŒ ์Šค์ผ€์ผ ์„ค์ •
  • minimumZoomScale: ์ตœ์†Œ ์คŒ ์Šค์ผ€์ผ ์„ค์ •
1
<ScrollView minimumZoomScale={1.0} maximumZoomScale={2.0}>
2
<!-- ~~~ -->
3
</ScrollView>

iOS ์‹œ๋ฎฌ๋ ˆ์ดํ„ฐ์—์„œ pinch ์คŒ์„ ํ•˜๋ ค๋ฉด?

  • optionํ‚ค๋ฅผ ๋ˆ„๋ฅด๊ณ  ๋“œ๋ž˜๊ทธ

์Šคํฌ๋กค๋ทฐ๋Š” ํ™”๋ฉด์—๋Š” ์•ˆ๋ณด์ด๋Š” ์•„์ดํ…œ๋„ ํ•œ๋ฒˆ์— ๋žœ๋”๋ง ํ•ด๋ฒ„๋ฆผ โ†’ ๋งŽ์€ ์•„์ดํ…œ์ด ์žˆ๋‹ค๋ฉด ๋žœ๋”๋ง ์‹œ๊ฐ„ ๊ธธ์–ด์ง

  • ์•„์ดํ…œ์ด ๋งŽ๋‹ค๋ฉด **List View**๋ฅผ ์‚ฌ์šฉ.

2.3 List View

2.3.1 FlatList

  • ํ™”๋ฉด์— ํ˜„์žฌ ๋ณด์ด๋Š” ๋ถ€๋ถ„๋งŒ ๋จผ์ € ๋žœ๋”๋ง ๋จ
  • props ์„ค๋ช…
    • data: ์ถœ๋ ฅํ•˜๊ณ ์ž ํ•˜๋Š” ๋ชจ๋“  ์•„์ดํ…œ๋“ค์˜ ์ •๋ณด๋ฅผ array(list) ํ˜•ํƒœ๋กœ ์ „๋‹ฌ
    • renderItem: ๊ฐ ์š”์†Œ๋“ค์„ ์–ด๋–ค ํฌ๋งท์œผ๋กœ ์ถœ๋ ฅํ•  ๊ฒƒ์ธ์ง€ ๊ตฌํ˜„ํ•˜๋Š” ๊ณณ
    • keyExtractor: ๊ฐ ์•„์ดํ…œ๋งˆ๋‹ค uniqueํ•œ key ๊ฐ’์„ ์คŒ (React์—์„œ์˜ key์™€ ๋™์ผํ•œ ์—ญํ• )
  • cf. https://reactnative.dev/docs/next/using-a-listview
1
import React from 'react'
2
import { FlatList, StyleSheet, Text, View } from 'react-native'
3
4
const styles = StyleSheet.create({
5
container: {
6
flex: 1,
7
paddingTop: 22,
8
},
9
item: {
10
padding: 10,
11
fontSize: 18,
12
height: 44,
13
},
14
})
15
16
const FlatListBasics = () => {
17
return (
18
<View style={styles.container}>
19
<FlatList
20
data={[
21
{ key: 'Devin' },
22
{ key: 'Dan' },
23
{ key: 'Dominic' },
24
{ key: 'Jackson' },
25
{ key: 'James' },
26
{ key: 'Joel' },
27
{ key: 'John' },
28
{ key: 'Jillian' },
29
{ key: 'Jimmy' },
30
{ key: 'Julie' },
31
]}
32
renderItem={({ item }) => <Text style={styles.item}>{item.key}</Text>}
33
/>
34
</View>
35
)
36
}
37
38
export default FlatListBasics

2.3.2 SectionList

  • FlatList๋“ค์„ ๊ตฌ๋ถ„ํ•  ์ˆ˜ ์žˆ๋Š” ์„ธ์…˜ ํ—ค๋”๊ฐ€ ์กด์žฌ (iOS์˜ UITableView์™€ ๋น„์Šทํ•จ)
  • props ์„ค๋ช…
    • sections: ์ถœ๋ ฅํ•˜๊ณ ์ž ํ•˜๋Š” ๋ชจ๋“  Section์˜ ์ •๋ณด๋ฅผ array(list) ํ˜•ํƒœ๋กœ ์ „๋‹ฌ
      • (๊ฐ ์„ธ์…˜์€ FlatList์ด๊ธฐ ๋•Œ๋ฌธ์— FlatList์˜ props์— ๋Œ€ํ•œ ์ •๋ณด๋ฅผ ์ •์˜ํ•ด์•ผ ํ•จ)
    • renderItem: ๊ฐ ์•„์ดํ…œ๋“ค์„ ์–ด๋–ค ํฌ๋งท์œผ๋กœ ์ถœ๋ ฅํ•  ๊ฒƒ์ธ์ง€ ๊ตฌํ˜„ํ•˜๋Š” ๊ณณ
    • renderSectionHeader: ์„ธ์…˜์„ ๊ตฌ๋ถ„ํ•˜๋Š” ํ—ค๋”๋ฅผ ๊ตฌํ˜„ํ•˜๋Š” ๊ณณ
    • keyExtractor: ๊ฐ ์•„์ดํ…œ๋งˆ๋‹ค uniqueํ•œ key ๊ฐ’์„ ์คŒ (React์—์„œ์˜ key์™€ ๋™์ผํ•œ ์—ญํ• )
  • cf. https://reactnative.dev/docs/sectionlist
1
import React from 'react'
2
import { StyleSheet, Text, View, SafeAreaView, SectionList, StatusBar } from 'react-native'
3
4
const DATA = [
5
{
6
title: 'Main dishes',
7
data: ['Pizza', 'Burger', 'Risotto'],
8
},
9
{
10
title: 'Sides',
11
data: ['French Fries', 'Onion Rings', 'Fried Shrimps'],
12
},
13
{
14
title: 'Drinks',
15
data: ['Water', 'Coke', 'Beer'],
16
},
17
{
18
title: 'Desserts',
19
data: ['Cheese Cake', 'Ice Cream'],
20
},
21
]
22
23
const SectionListBasics = () => (
24
<SafeAreaView style={styles.container}>
25
<SectionList
26
sections={DATA}
27
keyExtractor={(item, index) => item + index}
28
renderItem={({ item }) => (
29
<View style={styles.item}>
30
<Text style={styles.title}>{item}</Text>
31
</View>
32
)}
33
renderSectionHeader={({ section: { title } }) => <Text style={styles.header}>{title}</Text>}
34
/>
35
</SafeAreaView>
36
)
37
38
const styles = StyleSheet.create({
39
container: {
40
flex: 1,
41
paddingTop: StatusBar.currentHeight,
42
marginHorizontal: 16,
43
},
44
item: {
45
backgroundColor: '#f9c2ff',
46
padding: 20,
47
marginVertical: 8,
48
},
49
header: {
50
fontSize: 32,
51
backgroundColor: '#fff',
52
},
53
title: {
54
fontSize: 24,
55
},
56
})
57
58
export default SectionListBasics