JiSoo's Devlog
[React Native] 기초 본문
Text와 View는 React Native의 가장 중요한 내장 컴포넌트로서 JSX 코드에 사용된다
네이티브 기기는 브라우저 아니라서 DOM을 가지고 있지 않으니 HTML 요소를 지원하지 않는다
몇 가지 핵심 컴포넌트로 원하는 사용자 인터페이스 구축 가능
Button, Image, Text, View 등
React Native의 본질은 내장된 핵심 컴포넌트를 다루는 것
전체적인 앱 UI와 UI를 구성하는 커스텀 컴포넌트는 핵심 컴포넌트를 합쳐서 만드는 것
React Native에 의해 핵심 컴포넌트가 네이티브 UI 요소로 바뀐다
핵심 컴포넌트는 JSX 코드에서 합쳐서 직접 컴포넌트를 만들고 사용자 인터페이스를 구축한다
React Native에는 CSS가 없다!
브라우저가 아니기 때문에 CSS 코드 작성 불가 → 대신 스타일 적용
인라인 스타일 적용 or StyleSheet 객체 사용
App.js 파일 내 App 컴포넌트는 앱에 렌더링 되는 루트 컴포넌트
모든 UI 요소와 컴포넌트는 App 컴포넌트 산하에 자식이나 자손이 되어야 한다
div와 거의 똑같은 View에는 텍스트 삽입 불가
View는 다른 컴포넌트를 담고 배치하는 컴포넌트
Text 컴포넌트로 묶인 텍스트를 넣을 수 있고 텍스트 상자, 버튼 또는 이미지 같은 것들도 넣을 수 있다
View에 담기는 컴포넌트는 중첩해서 사용 가능
View는 스타일링을 쉽게 사용할 수 있게 해 주는데 자식 컴포넌트의 배치를 조절할 수 있다
버튼을 표시하려면 코어 컴포넌트를 가져온 다음 추가할 수 있다
웹처럼 열고 닫는 태그 사이에 캡션을 추가하는 게 아니라 자체적으로 닫는 요소로 title 프로퍼티를 추가하고 입력
<Button title="Tap me!" />
코어 컴포넌트로 항상 작업을 하게 되는데 이 컴포넌트를 결합해 전체 UI를 구축하게 되는 것!
스타일 적용 → style 프로퍼티 사용 (일부 요소에서 지원 ex) View, Text)
style 프로퍼티 추가한 후 값으로 JavaScript 객체 전달 가능
특정 콘텐츠를 담은 요소 자체를 스타일링하는 것
<Text style={{ margin: 16, borderWidth: 2, borderColor: "red", padding: 16 }}>
보통은 StyleSheet 객체 사용
JSX 코드와 스타일 코드를 명확히 구분해 주고 스타일 재사용이 가능하기 때문
스타일 프로퍼티를 입력할 때 편리한 자동 완성 기능으로 개발 작업이 조금 더 쉬워진다
코드 검증 기능으로 잘못된 스타일 객체나 값에 오류나 경고 표시
Color Reference · React Native
import { StyleSheet, Text, View, Button } from "react-native";
export default function App() {
return (
<View style={styles.container}>
<View>
<Text style={styles.dummyText}>Another piece of text!</Text>
</View>
<Text style={styles.dummyText}>Hello World!</Text>
<Button title="Tap me!" />
</View>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: "#fff",
alignItems: "center",
justifyContent: "center",
},
dummyText: {
margin: 16,
padding: 16,
borderWidth: 2,
borderColor: "blue",
},
});
TextInput 컴포넌트는 사용자가 텍스트를 입력할 수 있게 해주는 컴포넌트
<TextInput placeholder="Your course goal!" />
앱에서 레이아웃을 구축할 때 플렉스 박스는 아주 중요하다
몇 개의 스타일 프로퍼티로 컨테이너 내부에 요소를 배치하는 것으로 특정 요소가 차지하는 공간 제어 가능
컨테이너 상의 두 축이 중요!
flex: 1 사용 가능한 모든 공간 차지하도록 확장
flexDirection은 주요 축이 세로축일지 가로축일지 설정하는데 세로축이 column 가로축이 row
크기 입력할 때 보통은 숫자를 사용해 픽셀로 설정하는데 퍼센트로 설정도 가능
사용할 수 있는 너비는 해당 요소를 담고 있는 컨테이너가 정의한다
View는 특정 스타일을 설정하지 않아도 기본값으로 플렉스 박스를 사용한다
↔ 웹에서 div는 기본값으로 플렉스 박스를 사용하지 않는다
flexDirection
row-reverse 가로 반전
column-reverse 세로 반전
주축은 flexDirection을 따르는데 row라면 왼쪽에서 오른쪽, column이면 위에서 아래, column-reverse면 아래에서 위
교차축은 주축의 반대, 주축이 왼쪽에서 오른쪽이라면 교차축은 위에서 아래, 주축이 오른쪽에서 왼쪽이라면 교차축은 아래에서 위
justifyContent를 사용해 주축을 따라 정렬
alignItems를 사용해 교차축을 따라 요소 정렬
가능한 공간에서 어느 정도 차지할지는 자식 요소에서 설정 가능
View는 기본값으로 자식 요소가 필요한 공간만 차지
교차축은 부모 요소에서 설정
같은 플렉스 박스 내에서 flex 프로퍼티를 가진 모든 항목에 설정한 숫자에 따라 사용 가능한 공간 배분
플렉스 박스를 사용하는 View가 꼭 하나일 필요는 없다
<View
style={{
padding: 50,
flexDirection: "row",
width: "80%",
height: 300,
justifyContent: "space-around",
alignItems: "stretch",
}}
>
<View
style={{
backgroundColor: "red",
flex: 1,
justifyContent: "center",
alignItems: "center",
}}
>
<Text>1</Text>
</View>
<View
style={{
backgroundColor: "blue",
flex: 2,
justifyContent: "center",
alignItems: "center",
}}
>
<Text>2</Text>
</View>
<View
style={{
backgroundColor: "green",
flex: 1,
justifyContent: "center",
alignItems: "center",
}}
>
<Text>3</Text>
</View>
</View>
paddingHorizontal은 왼쪽과 오른쪽 패딩
이벤트 처리 방식은 웹 앱에서 사용하는 방식과 같다
이벤트 리스너를 추가해 이벤트 핸들러 함수에 연결하고 useState 훅을 사용해 컴포넌트에서 상태 관리
onChangeText 프로퍼티는 리액트 네이티브에서 제공하는 특수 이벤트 리스터 프로퍼티
함수를 값으로 취하며 함수를 지목하는 역할
매개변수로서 입력된 값을 제공한다
function goalInputHandler(enteredText) {
// 내용 입력값 가져오기
console.log(enteredText);
}
...
<TextInput
style={styles.textInput}
placeholder="Your course goal!"
onChangeText={goalInputHandler}
/>
onPress는 onClick과 비슷한 프로퍼티
값 입력받고 목록 리스트로 만들려면
function addGoalHandler() {
// 기존 목표 전개해 새로운 배열에 넣고 새로운 목표 추가
setCourseGoals((currentCourseGoals) => [
...currentCourseGoals,
enteredGoalText,
]);
}
map 메서드는 함수를 취한다
{courseGoals.map((goal) => (
<Text>{goal}</Text>
))}
데이터 목록을 출력하는 경우 목록에 있는 항목은 전부 개별 목록 항목을 식별하는 key 프로퍼티를 수신해야 한다
키에 전달하는 값은 출력하는 구체적인 값을 식별하는 고유한 항목이어야 한다
리액트 네이티브는 Text 컴포넌트를 해당하는 네이티브 위젯 즉 네이티브 UI 요소로 전환
Text 컴포넌트에 borderRadius를 적용했을 때 ↓
Android에서는 전환된 후 둥근 모서리로 나타나지만 iOS에서는 기본 네이티브 텍스트 출력 요소가 둥근 모서리를 지원하지 않는다
→ Text를 View로 감싸기
리액트 네이티브가 View를 컴파일해 얻는 기본 요소는 안드로이드나 iOS 모두에서 둥근 모서리를 지원한다
웹용 CSS와 달리 스타일은 연속적으로 적용되지 않는다!!
연속적인 속성 적용은 부모와 조상 요소의 스타일이 자식 및 하위 요소에 그대로 이어지는 CSS의 핵심 특성인데 이런 접근 방식을 취하지 않기 때문에 스타일 상속은 없다
View 안에 Text가 있고 View에서 텍스트 색상을 설정해도 Text 요소 안에 있는 텍스트에 영향 X
두 플랫폼을 대상으로 동일한 코드 기반을 사용하지만 내부에서 살펴보면 차이점이 몇몇 발생한다
화면을 스크롤 할 수 있게 만들려면 리액트 네이티브와 네이티브 플랫폼에 명시적으로 지시해야 한다
ScrollView는 View를 비롯한 컨테이너 요소에 스크롤 가능한 속성을 제공한다
스크롤 가능한 속성은 ScrollView에서 제공하지만 스크롤 가능한 영역은 부모 요소가 결정한다
→ 일반적인 View를 추가해 사용 가능한 높이를 제한하고 View가 차지할 높이를 설정하는 style 적용
<View style={styles.goalsContainer}>
<ScrollView>
{courseGoals.map((goal) => (
<View key={goal} style={styles.goalItem}>
<Text style={styles.goalText}>{goal}</Text>
</View>
))}
</ScrollView>
</View>
ScrollView의 alwaysBounceVertical을 false로 설정하면 튀어 오르기 효과가 사라진다
사용 가능한 공간을 넘어가면 스크롤할 수 있고 튀어 오르는 효과도 실행되지만 일정 높이를 채울 만한 콘텐츠가 없다면 튀어 오르지 않는다
ScrollView는 전체 UI가 렌더링 될 때마다 모든 자식 항목을 렌더링 해서 목록이 아주 길면 성능에 문제가 생길 수 있다
분량이 제한된 콘텐츠에는 적합하지만 길어질 수 있는 동적 목록에는 잘 사용하지 않는다
스크롤을 실현하는 FlatList 컴포넌트가 있는데 보이는 항목만 렌더링하고 화면 밖의 항목은 사용자가 스크롤해야 로딩 및 렌더링 된다
데이터를 수동으로 매핑하는 대신 해당 작업을 FlatList로 전달해 필요한 사항만 렌더링 하는 방식으로 효율적으로 렌더링
주요 프로퍼티로 data가 있는데 목록에서 출력할 데이터를 지정하는 역할을 한다
FlatList는 콘텐츠를 전달할 때 열고 닫는 텍스트 사이에 넣어 설정하지 않는다
renderItem 프로퍼티는 개별 데이터 항목을 렌더링하는 방법을 FlatList에 지시하는 함수를 값으로 갖는 프로퍼티
FlatList는 함수를 호출할 때마다 항목을 전달하고 새 항목을 렌더링 할 때 함수를 매번 호출한다
<FlatList
data={courseGoals}
renderItem={(itemData) => {
return (
<View key={goal} style={styles.goalItem}>
<Text style={styles.goalText}>{goal}</Text>
</View>
);
}}
alwaysBounceVertical={false}
/>
itemData는 index 프로퍼티 접근 권한도 제공해 렌더링 되는 다른 항목의 인덱스를 포함한다
itemData는 item 프로퍼티를 가지는데 렌더링되는 각 목록 항목에 대해 실제 데이터 항목을 하나씩 가진다
다양한 데이터 항목에 itemData.item으로 접근하는 것
FlatList 사용 시 목록 항목에 키를 추가하는 방법
→ 데이터의 값을 문자열 같은 원시 값에서 key 프로퍼티를 포함하는 객체로 변경
위 코드에서 data인 courseGoals 배열에 있는 항목을 객체로 만들기 위해
function addGoalHandler() {
setCourseGoals((currentCourseGoals) => [
...currentCourseGoals,
{ text: enteredGoalText, key: Math.random().toString() },
]);
}
FlatList는 데이터 배열에 있는 원시 값으로도 작동하지만 데이터가 객체 목록일 때 더 잘 작동한다
데이터로 객체 목록이 있고 모든 객체에 key 프로퍼티가 있다면 key 프로퍼티는 렌더링되는 항목에 자동으로 키로 사용된다
객체로 변경했기 때문에 단일 항목에 속한 데이터에 접근하기 위해 itemData.item.text로 넣어줘야 한다
keyExtractor 프로퍼티는 함수를 값으로 취하는데 모든 항목에서 키를 가져오려고 호출하는 함수
터치할 수 있게 만들려는 아이템을 Pressable 컴포넌트로 감싸면 된다
Pressable 내부에 있는 어떤 아이템이든 터치하면 onPress 프로퍼티가 제공된 함수를 활성화한다
filter은 자바스크립트 내장 메서드로 배열에서 호출할 수 있다
이전 배열에서 필터로 걸러낸 모든 아이템을 제외한 새로운 배열 반환
필터 자체도 true, false를 반환하는 함수를 사용하는데 true를 반환하면 아이템 유지, false를 반환하면 아이템 제외
내부함수를 배열 안에 있는 모든 아이템에 실행하기 때문에 아이템들을 매개변수로 취급하는 것
function deleteGoalHandler(id) {
setCourseGoals(currentCourseGoals=>{
return currentCourseGoals.filter((goal)=>goal.id !== id)
})
bind는 표준 자바스크립트 함수로 기본적으로 나중에 실행할 함수를 미리 조정할 수 있게 한다
bind의 첫 번째 인수는 곧 실행될 함수의 this 키워드, 두 번째 인수는 곧 호출될 함수에서 수신하는 첫 매개변수
안드로이드에서는 전용 android_ripple 프로퍼티를 설정해 물결 효과의 색상 설정이 가능하다
iOS에 스타일링을 추가하려면 Pressable에 style 프로퍼티를 추가해야 한다
style={({ pressed }) => pressed && styles.pressedItem}
모달이란 모바일 앱에서 메일 화면에 팝업 창이나 슬라이드 창처럼 오버레이 되는 것들을 말한다
<Modal visible={props.visible} animationType="slide">
이미지 게시하려면 제공되는 컴포넌트인 Image 사용
source로 이미지 경로를 전달해 주기 위해 require 함수를 사용해야 한다
require 함수에 이미지의 상대적인 경로 전달
StatusBar 컴포넌트로 상태 표시줄의 모양새를 상세히 조절할 수 있다
style 프로퍼티를 설정해 상태바의 밝기를 설정할 수 있다
'App > React Native' 카테고리의 다른 글
[React Native] 미니 게임 앱 (0) | 2024.04.29 |
---|---|
[React Native] 앱 디버깅 (0) | 2024.04.26 |
[React Native] 시작하기 (0) | 2024.04.22 |
[왕초보를 위한 React Native 101] Publshing our apps (0) | 2024.04.11 |
[왕초보를 위한 React Native 101] Travel hard app (3) | 2024.04.09 |