본문 바로가기

모바일 개발/React Native-이론

친구리스트 토글 버튼 만들기

<개요>

친구List를 화살표 키를 눌러 토글 시킬 것이다. 

토글 시킬려면 boolean 변수를 만들고, 우리가 상황에 따라 그 값의 상태를 변화 시켜주면 된다. (useState 이용)

변화가 필요한 곳은 friendSection, friendList  2가지 장소이다. 

boolean 변수가 false 일때, friendSection은 화살표를 위로 보게 하고, true 일때는 아래를 보게 만들어야 한다. 

friednList에서  boolean 변수가 false 일 때, return 값을 null로 줘서 안 보이게 만들고 true일 때 원래 로직을 보이게 만들면 된다. 여기서 쓰이는 것이 삼항 연산자 혹은 if문, &&문 이다. 

 

1. 코드 리뷰 

(1) App.js

    
    // useState로 boolean 변수의 상태 변화 나타내기. 
    // boolean 변수는 참/거짓 밖에 없어서 toggle button 만들기에 적합 
    const [isOpened, setIsOpened] =useState(true);


	// 클릭 시 로직 만들기 
    const onPressArrow = () => {
      console.log('clicked arrow');
      // 현재 상태에서 반대값으로 토글
      setIsOpened(!isOpened);
    };
    
    
    
    // 우리가 만든 boolean toggle 되는 변수를 넣어줘야 하는 파트
       <HomelessSection 
        idCardLen ={idCard.length} 
        onPressArrow = {onPressArrow}
        isOpened ={isOpened}
      />

      <HomelessList data = {idCard} isOpened={isOpened}/>

(2) HomelessSection.js (친구 수와 toggle 버튼 있는 곳)

export default (props) => {
  return (
    <View style={{flexDirection: "row", justifyContent: "space-between"}}>
      <Text style={{fontSize:15, color: "grey"}}> 일치율 90% 이상 :  {props.idCardLen}</Text>

		// 클릭시 toggle 됨.
      <TouchableOpacity onPress={props.onPressArrow}>
      	// boolean 변수가 참이냐 거짓이냐 따라 아이콘 달라짐.
      <MaterialIcons name={props.isOpened ? "keyboard-arrow-down" : "keyboard-arrow-up"} size={24} color="grey" />
      </TouchableOpacity>
    </View>
  )

}

(3) HomelessList.js (친구 리스트 배열이 있는 곳)

isOpened가 false 이면 컴포넌트의 return 값을 null 로 바꾼다. 

isOpened가 true 이면 컴포넌트의 return 값을 원래대로 놔둔다.

 

이를 구현하기 위한 Logic은 총 3가지가 있다. 

a. 삼항 연산자 사용

  /*
   * case 1  
   * 삼항 연산자 사용 
   * */
  return props.isOpened ? (
    <ScrollView contentContainerStyle ={{paddingBottom: bottomSpace}}>
      {props.data.map((item, index) => {
        return(
          <View  key={index}>
            <CandidateProfile
              name = {item.name}
              uri = {item.uri}
              location = {item.location}
              date = {item.date}
              persent = {item.persent}
            />

            <Margin top = {3}/>

          </View>
        )
      })}
    </ScrollView>
  ) : null;

b. if 문 사용

(추천! 하려는 것이 무엇인지 머릿글에서 바로 보이므로 가독성이 방법들 중 최고 높다.)

  /**
   * 2. if 문으로 예외 처리 앞에서 무슨 이야긴지 바로 알아서 가독성이 좋음.
   */

  if(!props.isOpened) return null;
  return(
    <ScrollView contentContainerStyle ={{paddingBottom: bottomSpace}}>
      {props.data.map((item, index) => {
        return (
          <View  key={index}>
            <CandidateProfile
              name = {item.name}
              uri = {item.uri}
              location = {item.location}
              date = {item.date}
              persent = {item.persent}
            />

            <Margin top = {3}/>

          </View>
        )
      })}
    </ScrollView>
  )

c. &&문 사용 

형태: 변수 &&(실행할 문장) 

변수가 false이면 실행할 문장 안 읽고 바로 false 반환, 변수가 true이면 그제서야 실행할 문장 읽고 수행

  /**
   * &&문 사용
   * 첫번째 인자가 false 이면 그대로 false 값 리턴 (&& 다음 문장은 check 안함), true이면 && 다음 문장 실행
   */

  return props.isOpened && (
    <ScrollView contentContainerStyle ={{paddingBottom: bottomSpace}}>
      {props.data.map((item, index) => {
        return(
          <View  key={index}>
            <CandidateProfile
              name = {item.name}
              uri = {item.uri}
              location = {item.location}
              date = {item.date}
              persent = {item.persent}
            />

            <Margin top = {3}/>

          </View>
        )
      })}
    </ScrollView>
  )

 

2. 스스로 해보기 

배운 것. Hook은 사용하려는 컴포넌트 안에서 선언 해야한다. 

const statusBarHeight = getStatusBarHeight(true);
const bottomSpace = getBottomSpace();



export default function App() {

  const [isOpened, setIsOpened]=useState(true);

  const onPressArrow = () => {
    console.log("clicked arrow")
    setIsOpened(!isOpened)
  }

  return (
    <View style={styles.container}>
      <Header />
      <Margin height = {10}/>
      <Profile
        uri={myProfile.uri}
        name={myProfile.name}
        introduction={myProfile.introduction}
      />
      <Margin height={15}/>
      <Division/>

      <Margin height={12}/>

      <FriendSection
        friendProfileLen = {friendProfiles.length}
        onPressArrow={onPressArrow}
        isOpened = {isOpened}
      />

      <FriendList
        data = {friendProfiles}
        isOpened = {isOpened}
      />
      
    </View>

  );
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    backgroundColor: '#fff',
    paddingTop: statusBarHeight,
    paddingHorizontal: 15,
  },
});
import { ScrollView, View } from "react-native"
import { getBottomSpace } from "react-native-iphone-x-helper"
import Margin from "./Margin";
import Profile from "./Profile"

const bottomSpace =getBottomSpace();

export default (props) => {
  if(!props.isOpened) {return null}
  return(
    <ScrollView showsVerticalScrollIndicator={false} contentContainerStyle={{paddingBottom: bottomSpace}}>
      
      {props.data.map((item, index) => (
        <View key={index}>
          <Profile
          uri={item.uri}
          name={item.name}
          introduction={item.introduction}
          />

          <Margin height={13}/>
        </View>
      ))}
    </ScrollView>
  )
}
import { View, Text, TouchableOpacity } from "react-native"
import { MaterialIcons } from '@expo/vector-icons'; 

export default (props) => {
  return (
    <View style={{flexDirection: "row", justifyContent: "space-between"}}>
      <Text style={{color: "grey"}}> 친구 {props.friendProfileLen}</Text>

      <TouchableOpacity onPress={props.onPressArrow}>
      <MaterialIcons name={props.isOpened ? "keyboard-arrow-down" : "keyboard-arrow-up"} size={24} color="lightgrey" />
      </TouchableOpacity>

    </View>
  )
}