Component, State, Props, useEffect @ recat-native

eesope·2021년 12월 15일
0

App Basic @SCC

목록 보기
2/5
post-thumbnail

import React,{useState,useEffect} from 'react';

리액트 기본 제공 함수들.
리액트 네이티브는 리액트 (React.js) 라이브러리 기반으로 만들어진 프레임워크이기에 기본 구조는 리액트를 닮음

{ useState, useEffect }

state

@ 리액트 -> 컴포넌트마다 데이터를 보유/관리할 수 있고, 그 데이터를 state 라고 부름

state 는 리액트 라이브러리에서 제공해주는 useState 로 생성하고, setState 로 정/변경
state 로 관리되는 데이터가 변경되면 화면이 바뀜

UI = component(state)
UI = f(state)

useEffect

화면이 그려진 다음 가장 먼저 실행되는 함수.
보통 데이터를 준비할 때 사용.

데이터 준비 = 데이터를 서버로부터 혹은 어디선가로부터 받은 후 state 에 반영한다는 뜻

실행 순서 = 화면 그려짐 -> useEffect 가 데이터 준비 -> state 가 업데이트 -> 화면 다시 그려짐

useEffect(() => {
 ...화면이 그려진 다음 가장 먼저 실행되야 할 코드 작성
}, [])

useState 사용법

[state, setState] 에서

state는 이 컴포넌트에서 관리될 상태 데이터를 담고 있는 변수
setState는 state를 변경시킬때 사용해야하는 함수

모두 다 useState가 제공해줌
useState()안에 전달되는 값은 state 초기값

import React,{useState,useEffect} from 'react';
import { StyleSheet, Text, View, Image, TouchableOpacity, ScrollView} from 'react-native';

import data from '../data.json';

export default function MainPage() {

  // state 설정하고
  const [state,setState] = useState([])

  // 데이터 준비 (현재 useEffect 를 거쳐야 state 에 데이터가 담김)
  useEffect(() => {
      setState(data)
  }, [])

  // 상태에서 data 꺼내 옴
  let tip = state.tip;

  return (
      // 전후 생략
    <View style={styles.cardContainer}>
           {tip.map((content,i)=>{
              return (<Card content={content} key={i}/>)})
          }

    </View>
      );
}

const styles = StyleSheet.create({});

로딩 화면의 필요성

위와 같이 작성되면
앱 기동 -> return () 구문 안에서 state 를 꺼내 쓰려할 때,
useEffect 를 거치치 않았기 때문에 처음 state에 데이터가 담기지 않아서,
꺼내올 수 없고, 오류가 발생함

-> state, component, useEffect 를 이용 로딩화면을 만들어 해결 가능

import React,{useState,useEffect} from 'react';
import { StyleSheet, Text, View, Image, TouchableOpacity, ScrollView} from 'react-native';

import data from '../data.json';
// 로딩 화면 하나 만들어서 설정하고
import Loading from '../components/Loading';

export default function MainPage() {

  // state 설정하고
  const [state,setState] = useState([])

  // 컴포넌트에 복수의 state 작성해도 ok
  // state 이름과 함수는 자유롭게 정의 가능
  // 초기 상태 값으로 list, true/false, dictionary, number, text 등 다양한 값이 들어갈 수 있음
  
  const [ready, setReady] = useState(true)
  
  // 데이터 준비 (useEffect 를 거쳐야 state 에 데이터가 담김)
  useEffect(() => {
    
  // 뒤의 1000 숫자 = 1초
  // setTimeout(() => {}, 1000) 은 , 뒤에 있는 숫자 (1초)만큼 지연됐다가 안에 있는 코드가 실행되는 지연 함수
    setTimeout(()=>{
      setState(data)
      setReady(false)
  }, 1000)
    
},[])

  // 상태에서 data 꺼내 옴
  let tip = state.tip;

  // 삼항연산자 사용, 처음 ready 값은 true 이므로 ? 바로 뒤의 값이 반환되어 화면이 그려짐
  // useEffect로 인해 데이터 준비 -> ready 값이 변경되면 : 뒤의 값이 반환되어 화면이 다시 그려짐
  
  return ready ? <Loading/> : (
      // 전후 생략
    <View style={styles.cardContainer}>
           {tip.map((content,i)=>{
              return (<Card content={content} key={i}/>)})
          }

    </View>
      );
}

const styles = StyleSheet.create({});
  • 실행 순서

1) ready 값이 true이므로 return 구문에서 ? 물음표 바로 뒤의 Loading 컴포넌트가 화면에 그려짐
2) 화면이 그려지고 난다음, 1초 후 상태값들이 채워지고 변경됨
3) ready 상태 값이 false가 됨
4) 상태값이 변경되었으므로 화면이 다시 그려짐
5) ready 값이 false 이므로 return 구문에서 : 콜론 뒤의 MainPage 컴포넌트가 화면에 그려짐

  • 로딩 화면 띄우는 다른 방법

엑스포의 기능 이용하는 방법도 있음
import AppLoading from 'expo-app-loading';

state 를 이용해서 카테고리 기능 추가

먼저 카테고리의 state 를 만들고,각 카테고리에 연결할 함수를 만들어서
각 카테고리에 따라 카테고리 state 상태 데이터를 새롭게 구성해준다.

import React,{useState,useEffect} from 'react';
import { StyleSheet, Text, View, Image, TouchableOpacity, ScrollView} from 'react-native';

import data from '../data.json';
import Loading from '../components/Loading';

export default function MainPage() {

  // 기존 데이터를 저장한 state 
  const [state, setState] = useState([])
  
  // 카테고리에 따라 다른 데이터를 그때그때 저장관리할 state
  const [cateState, setCateState] = useState([])
  
  const [ready, setReady] = useState(true)
  
  useEffect(() => {
	setTimeout(()=>{
      // 기존 데이터로 모두 초기화 준비, 아무 카테고리 선택 안했을 때 모두 출력
      let tip = data.tip;
      setState(tip)
      setCateState(tip)
      setReady(false)
  }, 1000)
    
},[])
  
  
  const category = (cate) => {
  	if(cate == 'All'){
    	// All 이면 원래 데이터를 담고 있는 상태값으로 다시 초기화
      setCateState(state)
    }else{
    	setCateState(state.filter((d))=>{
        	return d.category == cate
        })
    }
  }
  
  
  return ready ? <Loading/> : (
      // 전후 생략
    
     <ScrollView style={styles.middleContainer} horizontal indicatorStyle={"white"}>
      
        <TouchableOpacity style={styles.middleButtonAll} onPress={()=>{category('All')}}><Text style={styles.middleButtonTextAll}>All</Text></TouchableOpacity>
        <TouchableOpacity style={styles.middleButton01} onPress={()=>{category('Lifehack')}}><Text style={styles.middleButtonText}>Lifehack</Text></TouchableOpacity>
        <TouchableOpacity style={styles.middleButton03} onPress={()=>{category('For Cats')}}><Text style={styles.middleButtonText}>For Cats</Text></TouchableOpacity>
      
        <TouchableOpacity style={styles.middleButton04} onPress={()=>{category('Bookmarks')}}><Text style={styles.middleButtonText}>Bookmarks</Text></TouchableOpacity>
      </ScrollView>
  
    <View style={styles.cardContainer}>
           {cateState.map((content,i)=>{
              return (<Card content={content} key={i}/>)})
          }

    </View>
      );
}

const styles = StyleSheet.create({});
  • filter 함수 (반복문의 일종)

setCateState(state.filter((d))=>{ return d.category == cate })

배열.filter 를 걸면 배열의 요소를 하나씩 담아서 함수를 호출함.

리스트에서 조건문을 만족하는 내용을 모아 재 리스팅.
state 라는 json 리스트에서 각 딕셔너리를 d 라고 하고 리스트를 반복으로 돌렸을 때
-> d 딕셔너리의 키값 중 하나인 category 가 cate 의 내용과 일치하는 (true) 딕셔너리만을 가져와서
-> json 형태로 재 리스팅

profile
go simple 🧑🏻‍💻

0개의 댓글