RN) List형 레이아웃_ㅡmap()/FlatList/SectionList

소정·2023년 5월 31일
0

ReactNative

목록 보기
7/17

[1] map()

  • RN에서 제공하는 ListView용 컴포넌트를 사용하지 않고 리스트 형태 만들어보기

1~5번 ) JSX컴포넌트 객체를 변수에 저장하여 재사용하기

6번) 대량이 데이터 배열을 리스트로

  • 스트링은 뷰를 보여줄 수 없어서 adaper를 만들어야함(안드로이드)
  • 자스에서는 배열이 가진 메소드 중 'forEach' 사용하여 만들기

💡 forEach and map

forEach ( function (벨류, 인덱스, 어레이) ) - 각각에 접근할 때 마다 function 호출
다만, forEach는 접근해서 새로 만든 결과물을 받을 방법이 없음

map( function (벨류, 인덱스, 어레이) )
forEach와 같은 역할이지만 return이 있음

import React, {Component} from 'react'
import {View, Text, StyleSheet, Button} from 'react-native'


export default class MainComponent extends Component {


    render(): React.JSX.Element {

        //앱을 개발하면서 가장 많은 제작빈도를 가진 리스트 형태 레이아웃 만들기
        //RN에서 제공하는 ListView용 컴포넌트를 사용하지 않고 리스트 형태 만들어보기

        //1번 실습 ) 사용할 const변수 : JSX컴포넌트 객체를 변수에 저장
        const aaa : JSX.Element = <Text style={{margin : 2}}>Nice</Text>

        // 2번 실습 ) 변수 하나에 여러개 컴포넌트 저장하기 위해 큰 뷰그룹 사용
        const bbb : JSX.Element = <View style={{margin : 2}}><Text>Hello</Text><Button title="클릭"></Button></View>


        // 5번 실습 ) 배열의 요소로 JSX의 컴포넌트를 저장 배치
        const arr : [JSX.Element,JSX.Element,JSX.Element] = [ aaa, bbb, bbb ]  
        const arr2 : JSX.Element[] = [ aaa, bbb, bbb ]  //타입 다 같으면 이렇게 줄여 쓸 수 있음


        // 6번 실습 ) 리스트에 보여줄 대량이 데이터 배열
        let datas:String[] = ["aaa", "bbbb", "ccc", "ddd","aaa", "bbbb", "ccc", "ddd","aaa", "bbbb", "ccc", "ddd"]
        // 스트링은 뷰를 보여줄 수 없어서 adaper를 만들어야함 - 안드
        // 자스에서는 배열이 가진 메소드 중 'forEach' 사용하여 만들기 
        // forEach ( function (벨류, 인덱스, 어레이) ) - 각각에 접근할 때 마다 function 호출
        // 하지만 접근해서 새로 만든 결과물을 받을 방법이 없음
        // 따라서, forEach와 같은 역할이지만 return이 있는 ''''map()'''' 을 사용하여 한다!!
        // 배열의 map() 메소드를 이용하여 리턴 하여 온 것을 새로운 배열에 넣는다

        // 컴포넌트 형태로 출력하기 위해 datas를 컴포넌트를 포함한 새로운 배열로 만든다
        
        return (

            <View style={style.root}>
                <Text style={style.title}>List Layout Test</Text>

                {/* 1. 변수에 JSX 문법을 사용한 컴포넌트를 저장한 후에 사용 */}
                { aaa }

                {/* 변수에 저장되어 있으니 여러번 사용가능 */}
                { aaa }
                {/* { aaa } */}

                {/* 2. 변수 하나에 여러개 컴포넌트 넣어서 사용하기 */}
                { bbb }
                {/* { bbb } */}

                {/* 3. 함수(메소드)를 호출하여 JSX컴포넌트를 리턴받아 사용하기 */}
                {this.showItemView()}
                {/* {this.showItemView()} */}

                {/* 4. 함수를 호출하면서 파라미터 전달 */}
                { this.showItemView2("sam", "first", "indigo") }
                {/* { this.showItemView2("jeni", "second", "pink") } */}



                {/* 5. 배열변수에 jsx컴포넌트들을 요소로 넣어서 사용하기 */}
                {/* SJ는 배열을 출력하면 자동으로 요소값을 나열함!! */}
                {/* { arr } */}


                {/* 6. 실제 앱 개발과정에서는 대량의 데이터가 JSX컴포넌트 이기 보단 일반 데이터인 경우가 많음 */}
                {/* {datas}  Error - 일반 스트링 데이터는 컴포넌트가 아님*/}
                {datas.map( function( value, index, array ){
                                return (
                                    // 배열로 만든 아이템뷰는 식별자로 key 속성을 반드시 필수로 요구함
                                    <View key={index} style={style.itemView}>
                                        <Text>{value}</Text>
                                    </View>
                                )
                            } )
                }
                {/* 배열의 .map() 메소드 이용한 단점 */}
                {/* 1. key 속성을 개별적으로 지적해야 하는 것 */}
                {/* 2. 개수가 많아져도 자동 스크롤 되지 않음 */}
                {/* 3. 가로 스크롤이나 스크롤바 제어 등 리트스뷰에서의 기능이 없음 */}
                {/* 그래서 RN에서는 리스트뷰용 컴포넌트를 별도로 제공 */}

            </View>

        )


    }

    //4번 실습) 메소드
    showItemView2(name:String, btnTitle:String, btnColor:String) : JSX.Element{

        return (
            <View style={{margin : 2}}>
                <Text>{name}</Text>
                <Button title={btnTitle} color={btnColor}></Button>
            </View>
        )

    }


    // 3번 실습) 사용할 메소드
    showItemView():JSX.Element{
        return (
            <View style={{marginTop:16}}>
                <Text>Nice world</Text>
                <Button title='press me'></Button>
            </View>
        )
    }


}


//스타일스트 객체
const style= StyleSheet.create({
    root:{ flex:1, padding:16, },
    title:{ fontSize:24, fontWeight:'bold', color:'black'},
    itemView:{ 
        padding:16,
        margin:8,
        borderWidth:1,
        borderRadius:8,
     }
})

💡 배열의 .map() 메소드 이용한 단점

  1. key 속성을 개별적으로 지정해야 하는 것
  2. 개수가 많아져도 자동 스크롤 되지 않음
  3. 가로 스크롤이나 스크롤바 제어 등 리트스뷰에서의 기능이 없음

=> 그래서 RN에서는 리스트뷰용 컴포넌트를 별도로 제공



[2] FlatList

  • 일반적인 리스트 뷰
  • RN의 기본 리스트뷰 컴포넌트
  • 데이터가 view 넘어가면 스크롤 자동 생성
  • 필수 2가지 속성(props) - data, renderItem
    - data : 대량의 데이터, FlatList기 보여줄 데이터들
    - renderItem : 아이템 뷰 레이아웃, 아이템 하나의 모양(컴포넌트)를 만들어서 리턴하는 ''콜백함수'' 지정

import React, {Component} from "react";
import { View, Text, StyleSheet, FlatList, ListRenderItemInfo } from "react-native";



export default class Maine extends Component {

    //RN에서 ListView의 역할을 하는 컴포넌트 2가지 종류가 있음
    // 1. FlatList : 일반적인 리스트 뷰
    // 2. SectionList : 섹션에 따라 구분 지어서 리스트할 때 사용

    //먼저 FlatList에서 사용할 대량의 데이터 배열 - 데이터변경에 실시간 대응하려면 state 사용
    state : React.ComponentState = {
        //1.일반 간단한 string 문자열 배열
        datas : ["aaa", "bbbb", "ccc", "ddd"], //객체의 멤버로 만들땐 자료형 쓰지 않음
    }

    render(): React.JSX.Element {
        
        return (
            <View style={style.root}>
                <Text style={style.title}>FlatList</Text>

                {/* 1. FlatList : RN의 기본 리스트뷰 컴포넌트 */}
                {/* 필수 2가지 속성(props) - data, renderItem */}
                {/* data : 대량의 데이터, FlatList기 보여줄 데이터들 */}
                {/* renderItem : 아이템 뷰 레이아웃, 아이템 하나의 모양(컴포넌트)를 만들어서 리턴하는 ''콜백함수'' 지정 */}

                {/* <FlatList data={this.state.datas} renderItem={ ( obj : ListRenderItemInfo<any> ) => { //파라미터 1개 : 렌더링할 아이템정보 객체 (parameter) obj: ListRenderItemInfo<any>
                    return <Text> {obj.index} : {obj.item} </Text>
                } }></FlatList> */}

                {/* 위 renderIte의 obj 파라미터 객체를 구조분해 할당!! */}
                <FlatList data={this.state.datas} 
                    renderItem={ ( {item, index} ) => { //obj객체의 idex와 item 멤버를 뽑아옴
                    return <Text> {index} : {item} </Text>
                } }></FlatList>

            </View>
        )

    }

}

//스타일
const style=StyleSheet.create({
    root: {flex:1, padding:16},
    title: {fontSize :24, fontWeight : "bold", color:"black", textAlign:"center", paddingTop:8, paddingBottom:16},
    itemView: {
        borderWidth:1, 
        borderRadius:8,
        margin: 8,
        padding:8,
    }
})

import React, {Component} from "react";
import { View, Text, StyleSheet, FlatList, ListRenderItemInfo, TouchableOpacity, Alert, Image } from "react-native";



export default class Maine extends Component {

    //RN에서 ListView의 역할을 하는 컴포넌트 2가지 종류가 있음
    // 1. FlatList : 일반적인 리스트 뷰
    // 2. SectionList : 섹션에 따라 구분 지어서 리스트할 때 사용

    //먼저 FlatList에서 사용할 대량의 데이터 배열 - 데이터변경에 실시간 대응하려면 state 사용
    state : React.ComponentState = {
        //1.일반 간단한 string 문자열 배열
        datas : ["aaa", "bbbb", "ccc", "ddd","aaa", "bbbb", "ccc", "ddd","aaa", "bbbb", "ccc", "ddd"], //객체의 멤버로 만들땐 자료형 쓰지 않음
    
        //2. 텍스트가 2개 이미지가 1개 아이템 뷰 데이터들
        items : [
            {name : "sam", message:"Hello", img:{uri: 'https://cdn.pixabay.com/photo/2017/12/15/13/51/polynesia-3021072_640.jpg'}},
            {name : "lee", message:"hhihi", img:{uri: 'https://cdn.pixabay.com/photo/2018/08/21/23/29/forest-3622519_640.jpg'}},
            {name : "kim", message:"hehehe", img:{uri: 'https://cdn.pixabay.com/photo/2017/06/07/10/47/elephant-2380009_640.jpg'}},
            {name : "lisa", message:"hohoho", img:{uri: 'https://cdn.pixabay.com/photo/2016/11/14/04/45/elephant-1822636_640.jpg'}},
            {name : "jisoo", message:"ohoho", img:{uri: 'https://cdn.pixabay.com/photo/2017/05/08/13/15/bird-2295431_640.jpg'}},
            {name : "minee", message:"bye", img:{uri: 'https://cdn.pixabay.com/photo/2017/01/14/12/59/iceland-1979445_640.jpg'}},
            {name : "jene", message:"bye bye", img:{uri: 'https://cdn.pixabay.com/photo/2017/02/20/18/03/cat-2083492_640.jpg'}},
            {name : "rose", message:"안녕", img:{uri: 'https://cdn.pixabay.com/photo/2016/03/27/22/22/fox-1284512_640.jpg'}},
            {name : "bae", message:"내일봐", img:{uri: 'https://cdn.pixabay.com/photo/2014/11/30/14/11/cat-551554_640.jpg'}},
            {name : "moon", message:"리액트", img:{uri: 'https://cdn.pixabay.com/animation/2023/03/28/02/15/02-15-52-868_512.gif'}},
            {name : "son", message:"네이티브", img:{uri: 'https://cdn.pixabay.com/animation/2022/07/29/16/42/16-42-21-375_512.gif'}},
            {name : "big", message:"재밌다", img:{uri: 'https://cdn.pixabay.com/animation/2023/05/15/03/12/03-12-04-14_512.gif'}},
        ]
    }


    render(): React.JSX.Element {
        
        return (
            <View style={style.root}>
                <Text style={style.title}>FlatList</Text>

                {/* 1. FlatList : RN의 기본 리스트뷰 컴포넌트 */}
                {/* 필수 2가지 속성(props) - data, renderItem */}
                {/* data : 대량의 데이터, FlatList기 보여줄 데이터들 */}
                {/* renderItem : 아이템 뷰 레이아웃, 아이템 하나의 모양(컴포넌트)를 만들어서 리턴하는 ''콜백함수'' 지정 */}

                {/* <FlatList data={this.state.datas} renderItem={ ( obj : ListRenderItemInfo<any> ) => { //파라미터 1개 : 렌더링할 아이템정보 객체 (parameter) obj: ListRenderItemInfo<any>
                    return <Text> {obj.index} : {obj.item} </Text>
                } }></FlatList> */}

                {/* 위 renderIte의 obj 파라미터 객체를 구조분해 할당!! */}
                {/* <FlatList data={this.state.datas} 
                    renderItem={ ( {item, index} ) => { //obj객체의 idex와 item 멤버를 뽑아옴
                    return <Text> {index} : {item} </Text>
                } }></FlatList> */}

                {/* 아이템뷰의 클릭 이벤트 처리 */}
                {/* <FlatList data={this.state.datas} 
                    renderItem={ ( {item, index} ) => //리턴값 하나라서 중괄호랑 return 삭제, 파라미터에 {} 있으면 무조건 구조분해 할당임
                    <TouchableOpacity style={style.itemView} onPress={() => Alert.alert(item)}>
                        <Text>index : {index}</Text>
                        <Text>data : {item}</Text>
                    </TouchableOpacity>
                 }></FlatList> */}



                {/* 2. 텍스트 2개와 이미지 1개 아이템 뷰 모양 */}
                <FlatList data={this.state.items} 
                    renderItem={ ( {item, index} ) => //리턴값 하나라서 중괄호랑 return 삭제, 파라미터에 {} 있으면 무조건 구조분해 할당임
                    <TouchableOpacity style={style.itemWarp} onPress={() => this.showAlert(item, index)}>
                        <Image source={item.img} style={style.itemImg}></Image>
                        <View>
                            <Text style={style.itemName}>{item.name}</Text>
                            <Text style={style.itemMsg}>{item.message}</Text>
                        </View>
                    </TouchableOpacity>
                 }></FlatList>

            </View>
        )

    }

    showAlert = (item : any, index : number) => {
        Alert.alert(item.name + " : " + index)
    }

}

//스타일
const style=StyleSheet.create({
    root: {flex:1, padding:16},
    title: {fontSize :24, fontWeight : "bold", color:"black", textAlign:"center", paddingTop:8, paddingBottom:16},
    itemView: {
        borderWidth:1, 
        borderRadius:8,
        margin: 8,
        borderRadius:8,
    },
    itemWarp: {
        flexDirection : "row",
        borderWidth : 1,
        borderRadius:4,
        borderRadius:4,
        marginBottom: 12,
    },
    itemImg : {
        width : 120,
        height : 120,
        resizeMode : "cover",
        marginRight : 8,
    },
    itemName : {
        fontSize : 24,
        fontWeight : "bold",
        color : "black",
    },
    itemMsg : {
        fontSize : 16,
        fontStyle : "italic",
    }

})



[3] SectionList

  • 리스트뷰의 섹션별 헤더뷰를 가질 수 있는 SectionList 컴포넌트

💡 SectionList 객체의 필수!
SectionList의 세션 하나 객체에는 반드시 title, data 2개의 프로퍼티가 필요하다, 이름 정해져있음 못 바꿈!!!

💡 SectionList에 필요한 필수 속성 3개
1. sections : 세션에 해당하는 title과 data를 가진 배열
2. renderSectionHeader : 세션 별 title영역이 그려질 render 컴포넌트를 리턴하는 콜백함수 지정
3. renderItem : section별 item들(string)이 그려질 렌더뷰를 리턴하는 콜백 함수 지정[FlatList와 동일]


import React, {Component} from "react";
import  { View, Text, StyleSheet, SectionList, TouchableOpacity, Alert } from "react-native";

export default class Maine extends Component {

    //리스트뷰의 섹션별 헤더뷰를 가질 수 있는 SectionList 컴포넌트
    
    //대량의 데이터
    state:React.ComponentState = {
        //SectionList의 세션 하나 객체에는 반드시 title, data 2개의 프로퍼티가 필요하다, 이름 정해져있음 못 바꿈!!!
        sectionDatas : [
            {title: '한식', data:['백반', '비빔밥', '된장찌개']},
            {title: '중식', data:['짜장면', '짬뽕', '탕수육']},
            {title: '일식', data:['초밥', '라멘', '덮밥']},
        ]
    }

    render(): React.JSX.Element {
        
        return (
            <View style={style.root}>
                <Text style={style.title}>SectionList</Text>

                {/* SectionList에 필요한 필수 속성 3개 */}
                {/* 1. sections : 세션에 해당하는 title과 data를 가진 배열 */}
                {/* 2. renderSectionHeader : 세션 별 title영역이 그려질 render 컴포넌트를 리턴하는 콜백함수 지정 */}
                {/* 3. renderItem : section별 item들(string)이 그려질 렌더뷰를 리턴하는 콜백 함수 지정[FlatList와 동일]*/}

                <SectionList
                    sections={this.state.sectionDatas} //대량의 데이터 주기
                    renderSectionHeader={({section}) => { //헤더모양 - 위 sections 속성에 지정한 배열의 요소개수만큼 반복하여 헤더영역 컴포넌트 리턴
                        return (
                            <View style={style.sectionHeader}>
                                <Text style={style.sectionTitle}>{section.title}</Text>
                            </View>
                        )
                    }}
                    renderItem={({item, index, section})=>{ //아이템
                        return (
                            //section 별로 index번호가 다시 0부터 나옴
                            <TouchableOpacity style={style.sectionItem} onPress={() => Alert.alert(index +" : " +item+ "~" + section.title)}>
                                <Text>{item}</Text>
                            </TouchableOpacity>
                        )
                    }}
                    >

                </SectionList>

            </View>
        )

    }

}

//스타일
const style=StyleSheet.create({
    root: {flex:1, padding:16},
    title: {
        fontSize :24, 
        fontWeight : "bold", 
        color:"black", 
        textAlign:"center", 
        paddingTop:8, 
        paddingBottom:16
    },
    sectionHeader : {
        padding:8,
        backgroundColor: 'grey',
    },
    sectionTitle : {
        fontSize : 18,
        fontWeight : 'bold',
        color : 'black',
    },
    sectionItem : {
        padding : 8
    }

})
profile
보조기억장치

0개의 댓글