데보션앱 소개페이지 바로가기
로그인 선택

신고하기

CLOSE
신고사유 (대표 사유 1개)
상세내용 (선택)
0/200
  • 신고한 게시글은 더 이상 보이지 않습니다.
  • 이용약관과 운영정책에 따라 신고사유에 해당하는지 검토 후 조치됩니다.
  • 허위 신고인 경우, 신고자의 서비스 이용이 제한될 수 있으니 유의하시어 신중하게 신고해 주세요.
(이 회원이 작성한 모든 댓글과 커뮤니티 게시물이 보이지 않고, 알림도 오지 않습니다.)

미리보기

커뮤니티

      1,234

      badge 23.06.15

      글 등록

      카테고리를 선택해주세요.

      DEVOTEE를 활성화 시키면
      지금 작성한 커뮤니티 글에 대해 1개의 댓글을 달아줍니다.

      버튼을 누르면 글 수정 시 ChatGPT가 작성한 댓글이 수정됩니다.

      임시저장함에 저장되었습니다. 저장일시 : 2022.5.17 14:29:08

      임시저장함

      제목을 선택하시면 이어서 작성이 가능하며,
      최대 20건까지 저장합니다.
      컨텐츠 유형, 제목, 저장일시, 삭제로 이뤄진 임시저장 목록
      컨텐츠 유형 제목 저장일 삭제

      데보션 블로그 게재 요청

      CLOSE
      • *
      • *

      본인인증

      효율적인 데보션 서비스 이용 및
      고객님의 소중한 개인정보보호를 위해
      본인인증을 진행해주세요. 본인인증 미 진행 시 로그인이 제한됩니다.
      본인인증 실패

      본인인증 로그인에 실패하였습니다.
      회원이 아니시거나 본인인증 등록이
      완료되지 않은 사용자입니다.

      회원정보 연결

      [DEVOCEAN 스쿨] RN(React Native) 스터디 7주차

      Eden 23.06.30
      990 7 0

      안녕하세요. Teus님과 함께 React Native 스터디를 진행하고 있는 Eden입니다.

      스터디 7주차 포스팅 입니다.


      아이스 브레이킹 시간

      모두가 기대하는 아이스 브레이킹 시간입니다.

      (이거 하러 스터디에 오는건지도?)


      이번주는 지난주에 이어, 라이어 게임을 진행 했는데요

      플러터 개발자이신 관악구 미화원님이 직접! 플러터로 라이어게임 앱을 만들어오셨어요

      image.png

      (리액트 네이티브 스터디에서 사용한 플러터 앱 ㅋㅋㅋ )


      image.png

      라이어 게임 열심히 진행 중...누가 라이어냐...!



      스터디 내용

      이번주는 교재 9장 스터디 입니다

      (사진앱 만들기 과정 중 포스트 목록 만들기)

      그 중 일부를 소개합니다.


      1) PostCard 컴포넌트 만들기

      포스트의 정보를 보여주는 PostCard 컴포넌트를 만듭니다

      이 컴포넌트는 포스트의 목록을 세로로 나열하는 상황,

      그리고 나중에 사용자 프로필 화면에서 하나의 포스트를 조회하는 상황에서 사용합니다.

      이 컴포넌트에 필요한 Props는 다음과 같이 다섯 개입니다.

      • user: 작성자의 계정 정보 객체

      • photoURL: 사진 URL

      • description: 사진 설명

      • createdAt: 작성 날짜

      • postId: 포스트의 고유 ID

      postId 값은 화면에 보이는 값은 아니지만, 추후 포스트를 수정하거나 삭제할 때 필요합니다.

      components 디렉터리에 PostCard.js 파일을 생성해 다음 코드를 작성합니다

      components/PostCard.js
      
      import React, {useMemo} from 'react';
      import {View, StyleSheet, Text, Image, Pressable} from 'react-native';
      
      function PostCard({user, photoURL, description, createdAt, id}) {
        const date = useMemo(
          () => (createdAt ? new Date(createdAt._seconds * 1000) : new Date()),
          [createdAt],
        );
      
        const onOpenProfile = () => {
          // TODO: 사용자 프로필 화면 열기
        };
      
        return (
          <View style={styles.block}>
            <View style={[styles.head, styles.paddingBlock]}>
              <Pressable style={styles.profile} onPress={onOpenProfile}>
                source={
                  user.photoURL
                    ? {
                      uri: user.photoURL,
                    }
                  : require('../assets/user.png')
                }
                resizeMode="cover"
                style={styles.avatar}
              />
              <Text style={styles.displayName}>{user.displayName}</Text>
            </Pressable>
            </View>
            <Image
              source={{uri: photoURL}}
              style={styles.image}
              resizeMethod="resize"
              resizeMode="cover"
            />
            <View style={styles.paddingBlock}>
              <Text style={styles.description}>{description}</Text>
              <Text date={date} style={styles.date}>
                {date.toLocaleString()}
              </Text>
            </View>
          </View>
        );
      }
      
      const styles = StyleSheet.create({
        block: {
          paddingTop: 16,
          paddingBottom: 16,
        },
        avatar: {
          width: 32,
          height: 32,
          borderRadius: 16,
        },
        paddingBlock: {
          paddingHorizontal: 16,
        },
        head: {
          flexDirection: 'row',
          alignItems: 'center',
          justifyContent: 'space-between',
          marginBottom: 16,
        },
        profile: {
          flexDirection: 'row',
          alignItems: 'center',
        },
        displayName: {
          lineHeight: 16,
          fontSize: 16,
          marginLeft: 8,
          fontWeight: 'bold',
        },
        image: {
          backgroundColor: '#bdbdbd',
          width: '100%',
          aspectRatio: 1,
          marginBottom: 16,
        },
        description: {
          fontSize: 16,
          lineHeight: 24,
          marginBottom: 8,
        },
        date: {
          color: '#757575',
          fontSize: 12,
          lineHeight: 18,
        },
      });
      
      export default PostCard;

      해당 포스트가 자신의 포스트라면 우측 상단에 점 3개 아이콘을 보여주기 위해

      styles.head에 justifyContent: 'space-between' 스타일을 부여했습니다.

      이 아이콘을 누르면 사용자는 포스트를 삭제하거나 수정할 수 있습니다.

      그리고 사용자 프로필 이미지를 보여줄 때 만약 프로필 이미지가 존재하지 않으면

      assets 디렉터리에 저장한 기본 프로필 이미지를 보여주도록 설정했습니다.


      2) Firestore로 포스트 목록 조회하기

      포스트 정보를 보여줄 컴포넌트를 만들었으니,

      이제 Firestore로 포스트 목록을 조회 할 수 있게 합니다.

      lib/posts.js 파일을 열어서 다음 함수를 추가합니다.

      lib/posts.js
      
      (...)
      
      export async function getPosts() {
        const snapshot = await postsCollection.get();
        const posts = snapshot.docs.map((doc) => ({
          id: doc.id,
          ...doc.data(),
        }));
        return posts;
      }

      컬렉션의 get 함수를 호출하면 해당 컬렉션의 QuerySnapshot 객체가 반환되는데,

      QuerySnapshot 객체 내부에 docs라는 배열이 있고, 이 배열 안에 각 문서에 대한 정보가 있습니다.

      만약 조회 결과가 없다면 빈 배열이 나타납니다.

      문서 안의 데이터를 확인하려면 문서의 data 함수를 호출해야 합니다.

      QuerySnapshot을 받아온 다음, map 함수를 통해 id가 포함된 객체로 변환했습니다.

      data 함수를 호출한 결과에는 다음과 같이 데이터의 고유 ID 값이 존재하지 않기 때문에

      따로 넣어준 것입니다.

      {
        "createdAt": {
          "nanoseconds": 425000000,
          "seconds": 1620593805
        },
        "description": "vxcvzxcv",
        "photoURL": "https://firebasestorage.googleapis.com/v0/b/publicgallery-f77ea.appspot.com/o/photo%2Fundefined%2Fa22f1e90-2254-42f3-b151-40abaf952093.jpg?alt=media&token=1030d10b-dd2b-49a5-9a95-2dfe9c0ace87",
        "user": {
          "displayName": "aw35baw35b",
          "id": "XXi0CfuZe5b47EhkeVjzZ2VFtrg1",
          "photoURL": null
        }
      }


      3) FeedScreen에서 getPost 호출 후 FlatList로 보여주기

      이제 FeedScreen 화면이 보일 때 포스트 정보들을 띄워 보겠습니다.

      getPost 함수를 호출해 데이터를 조회한 뒤 FlatList를 사용합니다.

      화면에 FeedScreen 화면을 보여주는 시점에 특정 작업을 하려면 useEffect를 사용하면 됩니다.

      posts라는 배열 상태를 선언하고, useEffect에서 getPost를 호출한 뒤 결과값을 상태에 담은 뒤

      FlatList를 사용해 배열 안의 데이터에 기반해 PostCard 컴포넌트를 보여줍니다.

      screens/FeedScreen.js
      
      import React, {useEffect, useState} from 'react';
      import {FlatList} from 'react-native';
      import PostCard from '../components/PostCard';
      import {getPosts} from '../lib/posts';
      
      function FeedScreen() {
        const [posts, setPosts] = useState(null);
        
        useEffect(() => {
          // 컴포넌트가 처음 마운트될 때 포스트 목록을 조회한 후 `posts` 상태에 담기
          getPosts().then(setPosts);
        }, []);
      
        return (
          <FlatList
            data={posts}
            renderItem={renderItem}
            keyExtractor={(item) => item.id}
          />
        );
      }
      
      const renderItem = ({item}) => (
        <PostCard
          createdAt={item.createdAt}
          description={item.description}
          id={item.id}
          user={item.user}
          photoURL={item.photoURL}
        />
      );
      
      export default FeedScreen;

      이 코드에서 renderItem을 FeedScreen 함수 컴포넌트 밖에 선언 했는데,

      FlatList에서 보여지는 컴포넌트의 개수가 많을 경우에는

      컴포넌트 내부에서 renderItem을 렌더링할 때마다 매번 renderItem을 만드는 것보다는

      한 번만 만들고 재사용하는 것이 성능 면에서 더욱 좋습니다.

      이렇게 컴포넌트 밖에 선언하지 않고 useMemo를 사용하는 것도 좋은 방법입니다.

      여기까지 코드를 작성했다면 화면에 업로드한 사진의 정보가 나타납니다.


      조별 프로젝트 모임

      지난 주에 이어 각 조별 프로젝트를 진행했습니다

      image.png

      (1조, 전자 칠판에 열심히 디자인 중 )


      image.png

      (2조, 피그마 인듯? 암튼 여기도 디자인 중... )


      image.png

      (3조, 사진 찍는다고 했더니 갑자기 침묵을.....)


      이상 RN 스터디였습니다!

      다음주도 기대 해 주세요~~

      댓글 0

      DEVOTEE를 활성화 시키면
      지금 작성한 댓글에 AI가 댓글을 달아줍니다.

      Eden 님의 최신 블로그

      더보기
      동영상 기고하기