ReactNative Project - 카카오톡 친구목록 클론코딩 [2]
이전 게시글에 이어 친구리스트 toggle
로직과 TabBar
부분을 마무리하겠습니다.
리스트가 열려있는지에 대한 여부를 알 수 있는 isOpends
와 setIsOpend
를 useState를 사용해주었습니다.
초기값은 true로 주어 열러있도록 세팅해주었습니다.
화살표를 클릭했을 때 onPressArrow 함수에서 setIsOpend
를 통해 isOpend
가 반대값으로 세팅되게 해주었습니다.
FriendSection 과 FriendList에서 친구목록이 열려있는지 알 수 있도록 isOpend
를 추가해주었습니다.
FriendSection 에서 isOpend
의 값에 따라 up화살표 와 down화살표 가 선택되도록 설정해주었습니다.
화살표를 클릭했을 때, 화살표의 모양이 변경되고 로그가 잘 찍히는 것을 확인하였습니다.
console.log 부분은 지워주었습니다.
FriendList.js 에서는 다양하게 함수를 작성할 수 있습니다.
props.isOpend
가 true 일 때는 렌더링 해주고, 그렇지 않을 때는 null 을 반환합니다.
잘 토글되는 모습입니다.
가독성이 좋아서 자주 사용되는 방식입니다.
props.isOpend
가 열려있지 않은 상태면 null을 return합니다.
props.isOpend
가 열려있으면 작성해둔 ScrollView 를 return 해줍니다.
if문으로 예외처리 하는 방식이 삼항연산자 를 이용한 방식보다 자주 사용되는 이유는 한 눈에 봤을 때, return 되는 case 를 첫 줄에서 확인할 수 있다는 점입니다.
props.isOpend
가 true일 때, ScrollView 를 return 해줍니다.
isOpend
의 값이 false라면, &&
앞에서 멈추기 때문에 return false 가 됩니다.
false && 1 = false true && 2 = 2
첫 번째의 값이 false 인 경우 뒤의 값을 확인하지 않고 flase를 반환합니다.
첫 번째의 값이 true 인 경우에만 뒤의 값을 확인하여 반환해줍니다.
3가지 방법 중에서 저는 if문을 사용한 예외처리를 사용하였습니다.
에외처리되는 case를 첫 줄에서 확인할 수 있다는 점은 가독성에 좋기 때문입니다.
src 폴더에 TabBar.js 를 생성하고, 임시로 TabBar
를 구현해주었습니다.
TabBar를 제외한 나머지를 하나의 박스로 묶어서 flex: 1
로 꽉차게 설정해주고, TabBar가 차지하는 부분을 제외하고는 나머지가 flex: 1
로 차지하도록 구성을 변경해주었습니다.
View 를 최상단 부모 컴포넌트 아래에 추가하여 style 을 추가해주었고, 임시로 만들어둔 TabBar 도 추가해주었습니다.
영역을 구분하기 위해 임시로 yello 색상을 넣어주었고 삭제할겁니다.
TabBar 에는 padding
이 필요하지 않으므로 TabBar를 제외한 View 의 style 로 padding
을 옮겨주었습니다.
FriendList 에서 TabBar가 없었을때를 가정해서 padding: bottom
을 넣어주었던 부분도 삭제하엿습니다.
TabBar 는 클릭했을 때는 아이콘이 채워져있고, 그렇지 않을 때는 비워져있는 아이콘으로 구성하기 위해 선택 여부를 알 수 있는 state 가 필요합니다.
selectedTabIdx
와 setSeletedTabIdx
를 useState를 사용하여 초기값은 0 으로 세팅해주었습니다.
선택된 탭의 Index를 0,1,2,3 으로 임의로 정해주었고, 각각의 탭이 선택된 Index를 저장해줄겁니다.
TabBar 의 컴포넌트에서 현재 선택돼있는 selectedTabIdx
, 클릭한 setSelectedTabIdx
값을 모두 넘겨줍니다.
TabBar.js 에서 selectedTabIdx
, setSelectedTabIdx
값을 props 로 받아줍니다.
TabButton은 모두 동일한 구성을 갖고 있기 때문에 컴포넌트를 추가해줍니다.
터치가 가능한 TouchableOpacity를 사용해주었습니다.
클릭했을 때 처리를 위한 Onpress 와, 선택 여부에 대한 isSelected 의 값을 넣어주었습니다.
클릭했을 때의 아이콘과, 클릭하지 않았을 때의 아이콘이 필요합니다./
클릭했을 때의 아이콘 name activeIconName
과 , 클릭하지 않았을 때의 아이콘 name inactiveIconName
도 props 에 추가해주었습니다.
https://icons.expo.fyi/Index
expo에서 제공하는 아이콘을 사용해주었습닌다.
Fontisto 의 person
, persons
Ionicons 의 chatbubble
, chatbubble-outline
pricetag
, pricetag-outline"
, add-circle
, add-circle-outline
아이콘을 사용해주었습니다.
동일한 아이콘이 아니기 때문에 아이콘에 따라 사용해야할 컴포넌트가 달라집니다.
사용할 아이콘을 구분할 수 있는 isIconFontisto
, isIconIonicons
라는 boolean 값을 추가해주었고,
isIconFontisto
, isIconIonicons
값이 true 일 때만 아이콘을 렌더링하는 식으로 case를 분리해주었습니다.
isSelected
를 사용해서 선택여부에 따라 activeIconName
,inactiveIconName
도 정해지게 해주었습니다.
TabButton을 만들어주었고, 버튼마다 flex: 1
이 적용되도록 style을 추가해주었습니다.
style을 조정해주었습니다. 아이콘들이 중앙에 오도록 배치하였고, 영역을 알기 위해 추가하였던 색상도 조정해주었습니다.
탭을 선택함에 따라 아이콘이 변경됩니다.
ScrollView는 데이터가 화면을 벗어났을 때 스크롤을 생성해서 스와이프를 통해 벗어난 부분을 보여줍니다. 데이터의 양이 많이 않고 고정적인 경우 사용합니다.
친구목록을 렌더링 하기에는 적합하지 않습니다.
FlatList는 한 번에 모든 데이터를 불러오지 않고, 화면에 보여지는 부분만을 렌더링 해주기 때문에 ScrollView에 비해서 압도적인 성능을 보여줍니다.
헷갈리지 않도록 return을 새로 작성해주었습니다.
가장 최상단 컴포넌트는 마찬가지로 View로 해주었고, FlatList 를 추가해주었습니다.
필요한 속성은 첫 번쨰로 data
로, friendProfiles 를 넣어주었습니다.
다음으로는 renderItem
로, argument와 indext가 옵니다.
argument와 indext는 map
을 사용했을 때랑 동일하게 사용하지만, 한 번 오브젝트로 감싸주어야합니다.
key
부분은 FlatList 속성으로 따로 빼주었습니다.
마찬가지로 item 과 index가 인자로 오게됩니다.
사용하지 않는 argument 인 item
은 _
언더바로 처리해주었습니다.
Margin 부분은 ItemSeparatorComponent
로 따로 빼 주었습니다.
renderItem 부분도 위로 빼주었습니다.
가독성을 위해서 최대한 return 은 위에 빼두는것이 좋습니다.
친구 목록 부분을 FlatLsit 로 작성해주었으니 그 외에 나머지 부분들을 Header와 Footer 로 넣어줍니다.
내 프로필과, 친구 프로필의 크기를 다르게 하기 위해서
Header 의 Profile 에는 isMe={true}
로 보내주고
renderItem 에 있는 Profile 에는 `isMe={false} 로 보내주었습니다.
isMe
의 값에 따라 프로필 사이즈를 조정해주변됩니다.
ListHeaderComponent
와 ListFooterComponnet
속성을 이용해주었습니다.
stickyHeaderIndices
속성으로 헤더 부분을 고정시켜주었습니다.
배열의 형태로 고정해주고 싶은 헤더의 index 를 작성해주면됩니다.
showsVerticalScrollIndicator
스크롤바를 보이지 않게 해주었습니다. 보여도 무관합니다.
Header.js 의 style 에서 배경색도 변경해주었습니다.
isOpend
가 true일 때는 친구목록을 보여주고, 그렇지 않을때는 배열을 [], 배열의 길이를 0으로 만들어 주었습니다.
기존 Profile.js 코드입니다.
props.
으로 접근하던 방식을 배열 구조분해를 하면서 좀 더 쉽게 변경해주었습니다.
isMe
값에 따라서 이미지 size 를 다르게 해주었습니다.
이미지 크기가 조정된 모습입니다.
이름은 isMe
일 때는 bold, 아닐 때는 undifined 해주었습니다.
이름의 폰트 크기는 isME
일 때는 16, 아닐 때는 15.
Margin 부분도 isMe
일 때는 6, 아닐 때는 2.
상태메세지도 isMe
일 때는12, 아닐 때는 11 로 변경해주었습니다.
상태메세지가 없을 때는 이름이 가운데에 오도록 해주겠습니다.
introduction` 이 있을 때만 렌더링 해주면됩니다.
없을 경우 자동으로 가운데로 정렬됩니다.
해당 프로젝트에서 StyleSheet
, Inline
스타일링을 사용해보았습니다.
말 그대로 라인 안에 스타일링을 해주는 것입니다.
선호 취향에 따라 다르긴 하지만 스타일링이 너무 길지 않다면 Inline
으로 작성해 두면 해당 컴포넌트의 스타일링을 바로바로 확인할 수 있어StyleSheet
보다 읽기 편리합니다.
하지만 스타일링이 너무 길어지면 가독성이 좋지 않아지니 따로 빼주는 것이 좋습니다.
서비스가 커질수록 최적화 측면에서는 Inline
스타일링은 좋지 않습니다. 렌더링이 될 때마다 새로운 오브젝트가 계속해서 할당되기 때문에 성능에 좋지 못한 결과를 주게됩니다.
컴포넌트와 스타일링을 미리 선언해서, 렌더링 최적화와 가독성에 도움이됩니다.
expo 에서 제공해주는 styled-components 라이브러리를 통해 주어진 스타일로 리액트 구성요소를 쉽게 만들 수 있습니다.
웹, 모바일, 데스크탑에서 보편적인 스타일링을 할 수 있습니다.
> yarn add styled-components
> npm install styled-components
저는 yarn
을 이용해서 라이브러리를 설치해주었습니다.
Profile 부분에서만 적용해보도록 하겠습니다.
Profile.js 에서 import
해주었습니다.
View 를 사용하여 style을 적용해준 부분을 Container
라는 컴포넌트로 대체합니다.
기존에 View 를 사용하였기 떄문에 styled.View
로 해주었습니다.
Inline
스타일링이 Style Component
로 대체되었습니다.
Container
부분은 아무렇게나 이름을 지을 수 있습니다.
원하는 이름으로 가독성을 높일 수 있습니다.
Header에 있는 아이콘 4개를 터치 가능하게 하고 범위를 늘려주겠습니다.
paddingHorizontal
: 양 옆 padding 을 이미 6으로 설정해주었던 상태입니다.
hitSlop
: 기존 스타일을 침범하지 않고 터치범위만 늘려주었습니다.
paddingTop
, paddingBottom
으로 늘려주어도 되지만 그렇게 할 경우 기존에 세팅해둔 Margin을 제거하고 수정해야합니다.
hitSlop
을 통해 터치 영역만을 추가해줄 수 있습니다.
reactNative
의 expo
를 이용해서 카카오톡 친구창 UI를 구성해보았습니다.