FlatList의 기초

TL; DR



이 기사에서는 몇 가지 모범 사례에 따라 React Native에서 기본 플랫리스트를 구현하는 방법을 배웁니다.

플랫리스트란?


FlatList ScrollView,와 마찬가지로 스크롤 가능한 목록을 렌더링하는 기본 반응 구성 요소 중 하나이지만 훨씬 더 수행적입니다.

ScrollView 와 함께 .map 메서드를 사용할 수 없는 이유는 무엇입니까?



음... 할 수는 있지만 이 나쁜 습관으로 인해 성능이 많이 저하될 것입니다.
문제는 ScrollView와 함께 map 메서드를 사용하면 전체 데이터를 한 번에 로드하므로 구성 요소가 다시 렌더링될 때마다 데이터가 완전히 로드되고 다시 표시된다는 것입니다. 심지어 scrollview에 의해 숨겨진 데이터도 마찬가지입니다.

솔루션 - FlatList


FlatList는 이 성능 문제와 무한 스크롤, 지연 로딩과 같은 다른 문제를 해결하기 위해 나왔습니다.

간단한 목록 표시


FlatList에서 간단한 목록을 구현할 때 3props(속성)을 전달하기만 하면 됩니다.

데이터, 키 및 renderItem



몇 가지 모의 데이터로 시작하여 몇 가지 기본 스타일을 사용하여 플랫리스트에서 사용하겠습니다.

const App = () => {
  const [users, setUsers] = useState([
    { name: "Annya" },
    { name: "Regina" },
    { name: "Maria" },
    { name: "Kate" },
    { name: "Angelica" },
    { name: "Taylor" },
    { name: "Karol" },
    { name: "Olivia" },
    { name: "Emma" },
    { name: "Ava" },
    { name: "Isabella" },
  ]);

  const handleDelete = (name) => {
    setUsers((prevState) => prevState.filter((user) => user.name !== name));
  };

  return (
    <FlatList
      data={users}
      renderItem={({ item }) => {
        return (
          <View
            style={{
              flexDirection: "row",
              alignItems: "center",
              margin: 20,
              justifyContent: "space-between",
            }}
          >
            <Text style={{ fontSize: 20 }}>{item.name}</Text>

            <Button
              title="Delete"
              onPress={() => handleDelete(item.name)}
            ></Button>
          </View>
        );
      }}
    />
  );
}
export default App;


결과는 다음과 같습니다(지금은 경고 메시지에 대해 걱정하지 마십시오).


위의 코드에서 친구 배열을 data 소품에 전달하고 목록의 레이아웃을 renderItem 에 전달합니다.
renderItem 메서드는 data에서 항목을 가져와 목록에 렌더링합니다. 아시다시피 우리는 객체를 분해하고 항목에 직접 액세스하고 있으며 왜 이렇게 했습니까?
기본적으로 renderItem는 현재 개체를 자체 개체에 추가하므로 element.item.name를 통해 데이터에 액세스해야 합니다. 여기에서 요소를 원하는 이름으로 바꿀 수 있습니다. item.name를 통해 구조를 분해하고 액세스하는 것이 더 쉽습니다.

return 문 바로 앞에 console.log를 넣으면 outrenderItem의 출력이 됩니다.

그리고 삭제 버튼을 누르면 작동할까요?



예! 그러나 당신이 기대하는 것과는 다릅니다.

그렇다면 예상되는 동작은 무엇입니까?



버튼을 누르고 목록을 그대로 유지하고 선택한 항목만 삭제하려고 합니다.

그리고 분명히 우리가 기대하는 대로 작동하고 있지만... 그렇지 않습니다.

... 그럼 어떻게 작동합니까?



바로 지금 삭제 버튼을 누르면 전체 목록이 삭제되고 새 콘텐츠로 다시 렌더링됩니다. 우리는 이것을 우리 앱에 원하지 않습니다. 현재 목록에는 단순<Text>을 표시하는 11개의 요소만 있지만 이미지, 비디오 및 일부 무거운 콘텐츠를 표시하는 100개 이상의 요소가 있는 목록에서 이러한 동작이 발생한다고 상상할 수 있습니까? !

이 문제에 대한 답은 경고 메시지에 있습니다.

경고 메시지 및 키 소품



메시지를 살펴보면 다음과 같습니다.

VirtualizedList: missing keys for items, make sure to specify a key or id property on each item or provide a custom keyExtractor.



어떤 키 또는 a keyExtractor 를 전달해야 한다고 알려주는데 이 키의 목적은 무엇입니까?
이 키는 각 요소에 대한 고유한 참조가 되므로 내부적으로 FlatList에서 콘텐츠를 최적화된 방식으로 관리할 수 있습니다.

우리는 이 문제를 해결하기 위한 방법이 있습니다:

1. 객체에 직접 키(또는 ID) 추가:



const [users, setUsers] = useState([
    { name: "Annya", key: '1' },
    { name: "Regina", key: '2' },
    { name: "Maria", key: '3' },
    { name: "Kate" , key: '4'},
    { name: "Angelica" , key: '5'},
    { name: "Taylor" , key: '6'},
    { name: "Karol" , key: '7'},
    { name: "Olivia" , key: '8'},
    { name: "Emma" , key: '9'},
    { name: "Ava", key: '10' },
    { name: "Isabella" , key: '11'},
  ]);

이제 경고가 사라졌습니다.


이 경우 FlatList 자체를 수정할 필요조차 없습니다.

2. keyExtractor 사용 :



const App = () => {
  const [users, setUsers] = useState([
    { name: "Annya", uuid: '1' },
    { name: "Regina", uuid: '2' },
    { name: "Maria", uuid: '3' },
    { name: "Kate" , uuid: '4'},
    { name: "Angelica" , uuid: '5'},
    { name: "Taylor" , uuid: '6'},
    { name: "Karol" , uuid: '7'},
    { name: "Olivia" , uuid: '8'},
    { name: "Emma" , uuid: '9'},
    { name: "Ava", uuid: '10' },
    { name: "Isabella" , uuid: '11'},
  ]);

  const handleDelete = (name) => {
    setUsers((prevState) => prevState.filter((user) => user.name !== name));
  };

  return (
    <FlatList
      data={users}
      keyExtractor={(user) => user.uuid}
      renderItem={({ item }) => {
        return (
          <View
            style={{
              flexDirection: "row",
              alignItems: "center",
              margin: 20,
              justifyContent: "space-between",
            }}
          >
            <Text style={{ fontSize: 20 }}>{item.name}</Text>

            <Button
              title="Delete"
              onPress={() => handleDelete(item.name)}
            ></Button>
          </View>
        );
      }}
    />
  );
}
export default App;

객체에 사용자 지정 고유 키가 있는 경우(즉, uuid) keyExtractor 를 사용할 수 있습니다. 이 소품은 고유한 값을 반환하는 함수를 기대합니다.

마지막 최적화



이 샘플 앱은 매우 간단하므로 많은 최적화를 수행할 필요가 없지만 인라인 함수 사용에 대해 알아야 할 사항 중 하나입니다.

인라인 함수는 성능 문제를 일으킬 수 있는 모든 재렌더링에서 다시 생성됩니다. 그래서 다음과 같이 조정합니다.

const App = () => {
  const [users, setUsers] = useState([
    { name: "Annya", uuid: '1' },
    { name: "Regina", uuid: '2' },
    { name: "Maria", uuid: '3' },
    { name: "Kate" , uuid: '4'},
    { name: "Angelica" , uuid: '5'},
    { name: "Taylor" , uuid: '6'},
    { name: "Karol" , uuid: '7'},
    { name: "Olivia" , uuid: '8'},
    { name: "Emma" , uuid: '9'},
    { name: "Ava", uuid: '10' },
    { name: "Isabella" , uuid: '11'},
  ]);

  const handleDelete = (name) => {
    setUsers((prevState) => prevState.filter((user) => user.name !== name));
  };

  const _renderItem  = ({item}) => {
    return (
        <View
          style={{
            flexDirection: "row",
            alignItems: "center",
            margin: 20,
            justifyContent: "space-between",
          }}
        >
          <Text style={{ fontSize: 20 }}>{item.name}</Text>

          <Button
            title="Delete"
            onPress={() => handleDelete(item.name)}
          ></Button>
        </View>
      );
  }

  const keyExtractor = (user) => user.uuid;

  return (
    <FlatList
      data={users}
      keyExtractor={keyExtractor}
      renderItem={_renderItem}
    />
  );
}


이상으로 이 글이 도움이 되셨기를 바랍니다.
안녕! 😉

좋은 웹페이지 즐겨찾기