리액트 네이티브 - state를 이용한 카테고리 넣기 + filter함수

하이루·2021년 10월 20일
1

(data.Json)데이터 형태 --> category로 분류할 수 있게 데이터가 만들어져 있음(category키가 있음)

  {
      "tip":[
          {
              "idx":0,
              "category":"생활",
              "title":"먹다 남은 피자를 촉촉하게!",
              "image":"https://firebasestorage.googleapis.com/v0/b/sparta-image.appspot.com/o/lecture%2Fpizza.png?alt=media&token=1a099927-d818-45d4-b48a-7906fd0d2ad3",
              "desc":"먹다 남은 피자는 수분이 날라가기 때문에 처음처럼 맛있게 먹을 수 없는데요. 이럴 경우 그릇에 물을 받아 전자레인지 안에서 1분 30초에서 2분 정도 함께 돌려주면 촉촉하게 먹을 수 있습니다. 물이 전자레인지 안에서 수증기를 일으키고, 피자에 촉촉함을 더해줍니다.",
              "date":"2020.09.09"
          },
          {
              "idx":1,
              "category":"생활",
              "title":"바나나를 싱싱하게 보관하기",
              "image": "https://firebasestorage.googleapis.com/v0/b/sparta-image.appspot.com/o/lecture%2Fbanana.png?alt=media&token=886aeb87-7ff8-4498-8674-7e4f878b8845",
              "desc":"바나나에 날파리가 꼬이거나 금방 익어버리는 것을 예방하기 위한 방법인데요. 바나나 양쪽 끝을 자른 후, 보관용 케이스나 비닐봉지에 묶어 밀봉합니다. 그리고 냉장고에 넣어주면 되는데요. 하루에 1~2개씩 꺼내서 싱싱하게 먹을 수 있습니다.",
              "date":"2020.09.09"
          },
          {
              "idx":2,
              "category":"생활",
              "title":"셔츠에 묻은 볼펜 자국 없애기",
              "image": "https://firebasestorage.googleapis.com/v0/b/sparta-image.appspot.com/o/lecture%2Fshirt.png?alt=media&token=6388d9fb-f87f-4234-b580-46a2f918aab1",
              "desc":"셔츠를 자주 입는 사람의 경우, 종종 볼펜 자국이 묻기 마련인데요. 이럴 경우에는 집에 있는 물파스로 가볍게 지울 수 있습니다. 옷 뒷부분을 키친타올로 받쳐 번지는 것을 방지한 후, 볼펜 자국 있는 부분을 물파스로 눌러주고, 키친타올로 닦아냅니다.",
              "date":"2020.09.09"
          },
          {
              "idx":3,
              "category":"재테크",
              ......
              

예시 코드

import React,{useState,useEffect} from 'react';
import main from '../assets/main.png';
import { StyleSheet, Text, View, Image, TouchableOpacity, ScrollView} from 'react-native';
import data from '../data.json';
import Card from '../components/Card';
import Loading from '../components/Loading';


export default function MainPage() { 
  console.disableYellowBox = true;
  //return 구문 밖에서는 슬래시 두개 방식으로 주석

  //기존 꿀팁을 저장하고 있을 상태
  const [state,setState] = useState([])
  //카테고리에 따라 다른 꿀팁을 그때그때 저장관리할 상태
  const [cateState,setCateState] = useState([])

  //컴포넌트에 상태를 여러개 만들어도 됨
  //관리할 상태이름과 함수는 자유자재로 정의할 수 있음
  //초기 상태값으로 리스트, 참거짓형, 딕셔너리, 숫자, 문자 등등 다양하게 들어갈 수 있음.
  const [ready,setReady] = useState(true)

  useEffect(()=>{

    //뒤의 1000 숫자는 1초를 뜻함
    //1초 뒤에 실행되는 코드들이 담겨 있는 함수
    setTimeout(()=>{
        //꿀팁 데이터로 모두 초기화 준비
        let tip = data.tip;
        setState(tip)
        setCateState(tip)
        setReady(false)
    },1000)


  },[])

    const category = (cate) => {
        if(cate == "전체보기"){
            //전체보기면 원래 꿀팁 데이터를 담고 있는 상태값으로 다시 초기화
            setCateState(state)
        }else{
            setCateState(state.filter((d)=>{
                return d.category == cate
            }))
        }
    }


    let todayWeather = 10 + 17;
  let todayCondition = "흐림"

    //처음 ready 상태값은 true 이므로 ? 물음표 바로 뒤에 값이 반환(그려짐)됨
  //useEffect로 인해 데이터가 준비되고, ready 값이 변경되면 : 콜론 뒤의 값이 반환(그려짐)
  return ready ? <Loading/> :  (
    /*
      return 구문 안에서는 {슬래시 + * 방식으로 주석
    */
    <ScrollView style={styles.container}>
      <Text style={styles.title}>나만의 꿀팁</Text>
             <Text style={styles.weather}>오늘의 날씨: {todayWeather + '°C ' + todayCondition} </Text>
      <Image style={styles.mainImage} source={main}/>
      <ScrollView style={styles.middleContainer} horizontal indicatorStyle={"white"}>
        <TouchableOpacity style={styles.middleButtonAll} onPress={()=>{category('전체보기')}}><Text style={styles.middleButtonTextAll}>전체보기</Text></TouchableOpacity>
        <TouchableOpacity style={styles.middleButton01} onPress={()=>{category('생활')}}><Text style={styles.middleButtonText}>생활</Text></TouchableOpacity>
        <TouchableOpacity style={styles.middleButton02} onPress={()=>{category('재테크')}}><Text style={styles.middleButtonText}>재테크</Text></TouchableOpacity>
        <TouchableOpacity style={styles.middleButton03} onPress={()=>{category('반려견')}}><Text style={styles.middleButtonText}>반려견</Text></TouchableOpacity>
        <TouchableOpacity style={styles.middleButton04} onPress={()=>{category('꿀팁 찜')}}><Text style={styles.middleButtonText}>꿀팁 찜</Text></TouchableOpacity>
      </ScrollView>
      <View style={styles.cardContainer}>
         {/* 하나의 카드 영역을 나타내는 View */}
         {
          cateState.map((content,i)=>{
            return (<Card content={content} key={i}/>)
          })
        }

      </View>

    </ScrollView>
  );
}

1) 상태 생성 --> state,cateState,ready로 나눔

const [state,setState] = useState([])
-->기존 꿀팁을 저장하고 있을 상태

 data.Json의 모든 내용물이 들어있음
  

const [cateState,setCateState] = useState([])
-->카테고리에 따라 다른 꿀팁을 그때그때 저장관리할 상태

 data.Json에서 선택된 카테고리에 해당하는 내용물들이 들어있음

const [ready,setReady] = useState(true)
-->처음 화면이 그려질 때 상태에 데이터가 준비되었는지를 관리할 상태

2) useEffect로 상태초기화

 useEffect(()=>{

        //뒤의 1000 숫자는 1초를 뜻함
        //1초 뒤에 실행되는 코드들이 담겨 있는 함수
        setTimeout(()=>{
        
            //꿀팁 데이터로 모두 초기화 준비
            let tip = data.tip;
            setState(tip)
            setCateState(tip)
            setReady(false)
        },1000)


      },[])

--> 메인화면은 cateState에 있는 데이터를 가지고 화면을 그려나가기 때문에 처음에 아무 카테고리도 선택하지 않았을 때에는 모든 데이터가 나타나도록 cateState에도 tip을 할당해준다.

3) 선택한 카테고리에 따라 cateState에 데이터를 재할당하는 함수 선언

 const category = (cate) => {
          if(cate == "전체보기"){
              //전체보기면 원래 꿀팁 데이터를 담고 있는 상태값으로 다시 초기화
              setCateState(state)
          }else{
              setCateState(state.filter((d)=>{
                  return d.category == cate
              }))
          }
      }

--> 전체보기 카테고리를 제외하고는 다른 카테고리를 고를 경우 state상태(data.Json의 모든 데이터가 들어있는 상태)에서 해당 카테고리의 데이터만 filter함수로 걸러서 cateState에 재할당

filter함수

--> 반복문의 일종, 리스트에서 조건문을 만족하는 내용만 모아서 다시 리스팅

      state.filter((d)=>{
                return d.category == cate
            }))
   --> 위의 코드는 즉, state라는 Json리스트에서 각각의 딕셔너리를 d라고 해서 반복했을 때
   d딕셔너리의 키 중 하나인 category가 cate의 내용과 일치하는(즉, 해당 조건문이 true인) 딕셔너리만을 가져와서 
   다시 Json 형태로 리스트한 것
   
    a = 리스트.filter((d)=>{
                return 조건문
            }))

리스트를 반복으로 돌림(map함수 처럼) --> 반복하는 리스트의 내용을 d 라고 했을 때 return에 있는 조건문이 true인 d들을 모아서 리스트로 만들어 라턴(a에 할당)

  --> 즉 Json리스트에서 조건문을 만족하는 딕셔너리만 모아서 Json리스트로 만들 수 있음
      
      

4) 카테고리 버튼태그에 위의 함수가 적용되도록 설정

 <ScrollView style={styles.middleContainer} horizontal indicatorStyle={"white"}>
            <TouchableOpacity style={styles.middleButtonAll} onPress={()=>{category('전체보기')}}><Text style={styles.middleButtonTextAll}>전체보기</Text></TouchableOpacity>
            <TouchableOpacity style={styles.middleButton01} onPress={()=>{category('생활')}}><Text style={styles.middleButtonText}>생활</Text></TouchableOpacity>
            <TouchableOpacity style={styles.middleButton02} onPress={()=>{category('재테크')}}><Text style={styles.middleButtonText}>재테크</Text></TouchableOpacity>
            <TouchableOpacity style={styles.middleButton03} onPress={()=>{category('반려견')}}><Text style={styles.middleButtonText}>반려견</Text></TouchableOpacity>
            <TouchableOpacity style={styles.middleButton04} onPress={()=>{category('꿀팁 찜')}}><Text style={styles.middleButtonText}>꿀팁 찜</Text></TouchableOpacity>
          </ScrollView>
          
          
          

--> 카테고리 버튼에 해당하는 TouchableOpacity태그에 onPress 속성을 넣어서 버튼을 클릭하면
위의 함수(클릭한 카테고리에 해당하는 데이터를 cateState에 재할당하는 함수)를 실행하도록 만듬

--> cateState의 데이터가 변경되면 상태의 데이터 변경이므로 화면이 다시 그려짐

화면을 이루는 컴포넌트들은 cateState에 들어있는 데이터를 기준으로 화면을 채우게 되며 이것으로 카테고리 완성 !

 cateState.map((content,i)=>{
                return (<Card content={content} key={i}/>)
              })
            }

--> 카테고리를 클릭 --> 함수 실행 --> 해당 카테고리에 해당하는 데이터만 state에서 선별되어 cateState에 재할당 --> 상태(cateState)의 데이터가 변경되었으므로 화면을 다시 그림 --> 변경된 cateState를 기준으로 해당 데이터들을 map으로 하나씩 화면에 그려줌

profile
ㅎㅎ

0개의 댓글