ScrollView
콘텐츠에 스크롤을 추가할때 유용하다.
예를 들어 기사가 너무 길어 화면에 다 안들어가거나 사용자가 어떤 장치를 이용할 지 모르는 상태에서 기사를 스크롤 할 수 있도록 설정해야 하는 상황에서 사용
전체 UI가 렌더링될 때마다 안에 있는 항목을 전부 렌더링 한다. 즉 모든 자식 항목을 렌더링한다. 성능에 문제가 생김 앱이 느려짐 끝이 정해진 분량이 제한된 콘텐츠에서만 사용 권장
import { useState } from "react";
import {
StyleSheet,
Text,
View,
Button,
TextInput,
ScrollView,
FlatList
} from "react-native";
export default function App() {
const [enteredGoalText, setEnteredGoalText] = useState("");
const [courseGoals, setCourseGoals] = useState([]);
function goalInputHandler(enteredText) {
setEnteredGoalText(enteredText);
}
function addGoalHandler() {
setCourseGoals((currentCourseGoals) => [
...currentCourseGoals,
enteredGoalText,
]);
}
return (
<View style={styles.appContainer}>
<View style={styles.inputContainer}>
<TextInput
style={styles.textInput}
placeholder="Your course goal!"
onChangeText={goalInputHandler}
/>
<Button title="Add Goal" onPress={addGoalHandler} />
</View>
<View style={styles.goalsContainer}>
<ScrollView alwaysBounceVertical={false}>
{courseGoals.map((goal) => (
<View style={styles.goalItem} key={goal}>
<Text style={styles.goalText}>{goal}</Text>
</View>
))}
</ScrollView>
</View>
</View>
);
}
FlatList
화면에 보이는 부분만 렌더링하고 화면 밖의 항목은 사용자가 스크롤해야 로딩 및 렌더링 된다.
내부적으로 항목이 보이기 전에 로딩과 렌더링을 시작하도록 작은 임계값은 가지는데 사용자가 목록을 스크롤하면서 항목에 가까워질 때만 해당 항목을 렌더링한다. 필요할 때 데이터를 로딩하는 최적화 작업을 제외하면 내부적으로 구현 방식은 거의 유사
위의 코드와 다른 점은 ScrollView 를 FlatList로 대치하였고 데이터를 수동으로 매핑하는 커스텀 매핑 코드를 삭제하고 해당 작업을 FlatList 로 전달해서 필요한 사항만 렌더링하는 방식으로 목록을 효율적으로 렌더링 작업 해준다.
import { useState } from "react";
import {
StyleSheet,
Text,
View,
Button,
TextInput,
ScrollView,
FlatList,
} from "react-native";
export default function App() {
const [enteredGoalText, setEnteredGoalText] = useState("");
const [courseGoals, setCourseGoals] = useState([]);
function goalInputHandler(enteredText) {
setEnteredGoalText(enteredText);
}
function addGoalHandler() {
setCourseGoals((currentCourseGoals) => [
...currentCourseGoals,
enteredGoalText,
]);
}
return (
<View style={styles.appContainer}>
<View style={styles.inputContainer}>
<TextInput
style={styles.textInput}
placeholder="Your course goal!"
onChangeText={goalInputHandler}
/>
<Button title="Add Goal" onPress={addGoalHandler} />
</View>
<View style={styles.goalsContainer}>
<FlatList
//필수 프로퍼티 data : 목록에서 출력할 데이터를 지정하는 역할로 현재 코드에서는 courseGoals 으로 목록으로 출력할 데이터니까 데이터에 값으로 전달
//필수 프로퍼티 render Item : 개별 데이터 항목을 렌더링하는 방법을 FlatList에 지시하는 함수를 값으로 갖는 프로퍼티 함수는 자동으로 개별항목을 매개변수로 받는다.
//(itemData)로 정하는 이유는 값뿐만 아니라 메타데이터까지 포함하는 객체니까
//temData.index는 index 프로퍼티 접근 권한도 제공ㅡ렌더링 되는 다른 항목의 인덱스 포함
//중괄호안에 주어진 항목에 대해 렌더링할 JSX코드로 반환
data={courseGoals}
renderItem={(itemData) => {
itemData.index
return (
<View style={styles.goalItem} key={goal}>
{/* 여기서 중요한부분 {itemData.item} 으로 렌더링되는 각 목록 항목에 대해 실제 데이터 항목을 하나씩 가짐,여기 있는 다양한 데이터 항복에 itemData.item으로 접근*/}
<Text style={styles.goalText}>{itemData.item}</Text>
</View>
);
}}
alwaysBounceVertical={false}
/>
</View>
</View>
);
}
여기서 ..key 값 빠졌는데 목록항목에 키를 추가하는 주요 방법은 두 가지가 있다.
첫번째,
데이터의 값을 여기있는 문자열 같은 원시 값에서 key 프로퍼티를 포함하는 객체로 변경
import { useState } from "react";
import {
StyleSheet,
Text,
View,
Button,
TextInput,
ScrollView,
FlatList,
} from "react-native";
export default function App() {
const [enteredGoalText, setEnteredGoalText] = useState("");
const [courseGoals, setCourseGoals] = useState([]);
function goalInputHandler(enteredText) {
setEnteredGoalText(enteredText);
}
function addGoalHandler() {
setCourseGoals((currentCourseGoals) => [
...currentCourseGoals,
// 여기에 실제 목표 테스트를 포함하는 text프로퍼티를 넣어주고 unique key를 넣어준다.
//데이터 배열의 데이커가 객체 목록일 때 더 잘 작동함
{text:enteredGoalText, key: Math.random().toString()},
]);
}
return (
<View style={styles.appContainer}>
<View style={styles.inputContainer}>
<TextInput
style={styles.textInput}
placeholder="Your course goal!"
onChangeText={goalInputHandler}
/>
<Button title="Add Goal" onPress={addGoalHandler} />
</View>
<View style={styles.goalsContainer}>
<FlatList
//필수 프로퍼티 data : 목록에서 출력할 데이터를 지정하는 역할로 현재 코드에서는 courseGoals 으로 목록으로 출력할 데이터니까 데이터에 값으로 전달
//필수 프로퍼티 render Item : 개별 데이터 항목을 렌더링하는 방법을 FlatList에 지시하는 함수를 값으로 갖는 프로퍼티 함수는 자동으로 개별항목을 매개변수로 받는다.
//(itemData)로 정하는 이유는 값뿐만 아니라 메타데이터까지 포함하는 객체니까
//itemData.index는 index 프로퍼티 접근 권한도 제공ㅡ렌더링 되는 다른 항목의 인덱스 포함
//중괄호안에 주어진 항목에 대해 렌더링할 JSX코드로 반환
data={courseGoals}
renderItem={(itemData) => {
itemData.index;
return (
<View style={styles.goalItem}>
{/* 여기서 중요한부분 {itemData.item} 으로 렌더링되는 각 목록 항목에 대해 실제 데이터 항목을 하나씩 가짐,여기 있는 다양한 데이터 항복에 itemData.item으로 접근*/}
<Text style={styles.goalText}>{itemData.item.text}</Text>
</View>
);
}}
alwaysBounceVertical={false}
/>
</View>
</View>
);
}
두번째 API에서 데이터를 가져와서 변형할 수 없는 상황에서 입력 데이터에 key프로퍼티 설정
import { useState } from "react";
import {
StyleSheet,
Text,
View,
Button,
TextInput,
ScrollView,
FlatList,
} from "react-native";
export default function App() {
const [enteredGoalText, setEnteredGoalText] = useState("");
const [courseGoals, setCourseGoals] = useState([]);
function goalInputHandler(enteredText) {
setEnteredGoalText(enteredText);
}
function addGoalHandler() {
setCourseGoals((currentCourseGoals) => [
...currentCourseGoals,
//id : 고유한 id 를 만들고(하지만 잘 못된 이름 일 수도 있다. 여기 목록은 id 프로퍼티가 아닌 key프로퍼티를 찾기 때문!~)
{ text: enteredGoalText, id: Math.random().toString() },
]);
}
return (
<View style={styles.appContainer}>
<View style={styles.inputContainer}>
<TextInput
style={styles.textInput}
placeholder="Your course goal!"
onChangeText={goalInputHandler}
/>
<Button title="Add Goal" onPress={addGoalHandler} />
</View>
<View style={styles.goalsContainer}>
<FlatList
//렌더링되는 목록 항목마다 이 함수를 호출
data={courseGoals}
renderItem={(itemData) => {
itemData.index;
return (
<View style={styles.goalItem}>
{/* 여기서 중요한부분 {itemData.item} 으로 렌더링되는 각 목록 항목에 대해 실제 데이터 항목을 하나씩 가짐,여기 있는 다양한 데이터 항복에 itemData.item으로 접근*/}
<Text style={styles.goalText}>{itemData.item.text}</Text>
</View>
);
}}
//keyExtractor프로퍼티는 모든 항목에서 키를 가져오려고 호출하는 함수로 함수를 값으로 취하는데
//이 함수가 자동으로 수신하는 두 매개변수의 값 item 과 index는 FlatList가 함수를 호출할때 제공하는 값
//따라서 여기에서 키를 반환
keyExtractor={(item, index) => {
return item.id;
}}
alwaysBounceVertical={false}
/>
</View>
</View>
);
}