[React Native-Expo] ScrollView vs FlatList

grace·2023년 2월 7일
0

React

목록 보기
6/10
post-thumbnail

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>
  );
}

profile
미래의 개발자!

0개의 댓글