본문 바로가기
코딩생활/ReactNative

[React Native] 3-6 글 목록 보여주기

by InfoJun 2023. 3. 16.
반응형

FeedListItem 컴포넌트 만들기

 

먼저 FeedListItem 컴포넌트를 만들어야 합니다.

 

이 컴포넌트는 log 객체를 Props로 받아와서 알맞은 위치에 보여줄 것 입니다.

 

글 목록에서 화면에 body를 보여줄 때는 전체 내용을 보여주지 않습니다.

 

줄 바꿈 문자를 모두 없애야하고, 길이가 100자 이상이면 줄임표를 사용해야합니다.

 

이런 작업을 하는 truncate라는 함수도 따로 선언해주겠습니다.

 

그리고 추후 이 항목을 선택하려면 WriteScreen을 다시 띄워서 전체 내용을 볼 수 있게 해줘야 하기 때문에

 

Pressable 컴포넌트도 사용할 것입니다.

 

components/FeedListItem.js

import React from 'react';
import {Platform, Pressable, StyleSheet, Text} from 'react-native';

function truncate(text) {
  //정규식을 사용해 모든 줄 바꿈 문자 제거
  const replaced = text.replace(/\n/g, ' ');
  if (replaced.length <= 100) {
    return replaced;
  }
  return replaced.slice(0, 100).concat('...');
}

function FeedListItem({log}) {
  const {title, body, date} = log;
  return (
    <Pressable
      style={pressed => [
        styles.block,
        Platform.OS === 'ios' && pressed && {backgroundColor: '#efefef'},
      ]}
      android_ripple={{color: '#ededed'}}>
      <Text style={styles.date}>{new Date(date).toLocaleDateString()}</Text>
      <Text style={styles.title}>{title}</Text>
      <Text style={styles.body}>{truncate(body)}</Text>
    </Pressable>
  );
}

const styles = StyleSheet.create({
  block: {
    backgroundColor: 'white',
    paddingHorizontal: 16,
    paddingVertical: 24,
  },
  date: {
    fontSize: 12,
    color: '#546e7a',
    marginBottom: 8,
  },
  title: {
    color: '#263238',
    fontSize: 18,
    fontWeight: 'bold',
    marginBottom: 8,
  },
  body: {
    color: '#37474f',
    fontSize: 16,
    lineHeight: 21,
  },
});

export default FeedListItem;

FeedList 컴포넌트 만들기

 

이번엔 FeedList 컴포넌트를 만들 것입니다.

 

이 컴포넌트는 logs라는 Props를 받아와서 FlatList를 통해 여러 항목을 보여줄 것입니다.

 

FeedsScreen에서 FlatList를 바로 사용하지 않고 FeedList 컴포넌트를 따로 만드는 이유는

 

추후 달력 화면에서 재활용할 것이기 때문입니다.

 

components/FeedList.js

import React from 'react';
import {View, StyleSheet, FlatList} from 'react-native';
import FeedListItem from './FeedListItem';

function FeedList({logs}) {
  return (
    <FeedList
      data={logs}
      style={styles.block}
      renderItem={({item}) => <FeedListItem log={item} />}
      keyExtractor={log => log.id}
      ItemSeparatorComponent={() => <View style={styles.separator} />}
    />
  );
}

const styles = StyleSheet.create({
  block: {flex: 1},
  separator: {
    backgroundColor: '#e0e0e0',
    height: 1,
    width: '100%',
  },
});

export default FeedList;

 

이후 사용해보겠습니다.

 

screens/FeedsScreen.js

import React, {useContext} from 'react';
import {View, StyleSheet, TextInput} from 'react-native';
import LogContext from '../contexts/LogContext';
import FloatingWriteButton from '../components/FloatingWriteButton';
import FeedList from '../components/FeedList';

function FeedsScreen() {
  const {logs} = useContext(LogContext);

  return (
    <View style={styles.block}>
      <FeedList logs={logs} />     //추가
      <FloatingWriteButton />
    </View>
  );
}

const styles = StyleSheet.create({
  block: {
    flex: 1,
  },
});

export default FeedsScreen;

 

새 로그를 작성하여 잘 나타나는지 확인해보세요.

 


date-fns로 날짜 포맷팅하기

현재 FeedListItem에서 시간을 보여줄 때 Date 객채의 toLocaleString()을 사용하고있는데

 

작성 시간에 따라 다음과 같은 형식으로 보이게 하겠습니다.

  • 방금 전
  • 3분 전
  • 1시간 전
  • 3일 전
  • 2023년 3월 15일 07:00

이 때 유용하게 사용할 수 있는 라이브러리가 date-fns 입니다.

 

$ yarn add date-fns

다음 라이브러리에서 불러와 사용할 함수는 다음과 같습니다.

  • fromatDistanceTonow : 현재 시각을 기준으로 단어를 사용해 시간을 나타냅니다.(ex : 5분전)
  • format : 다양한 형태로 날짜를 포맷팅합니다

 

components/FeedListItem.js

import React from 'react';
import {Platform, Pressable, StyleSheet, Text, View} from 'react-native';
import {format, formatDistanceToNow} from 'date-fns';
import {ko} from 'date-fns/locale';

function formatDate(date) {
  const d = new Date(date);
  const now = Date.now();
  const diff = (now - d.getTime()) / 1000;

  if (diff < 60 * 1) {
    return '방금 전';
  }
  if (diff < 60 * 60 * 24 * 3) {
    return formatDistanceToNow(d, {addSuffix: true});
  }
  return format(d, 'PPP EEE p');
}

function truncate(text) {
  // 정규식을 사용해 모든 줄 바꿈 문자 제거
  const replaced = text.replace(/\n/g, ' ');
  if (replaced.length <= 100) {
    return replaced;
  }
  return replaced.slice(0, 100).concat('...');
}

function FeedListItem({log}) {
  const {title, body, date} = log; // 사용하기 편하게 객체 구조 분해 할당

  return (
    <Pressable
      style={({pressed}) => [
        styles.block,
        Platform.OS === 'ios' && pressed && {backgroundColor: '#efefef'},
      ]}
      android_ripple={{color: '#ededed'}}>
      <Text style={styles.date}>{formatDate(date)}</Text>
      <Text style={styles.title}>{title}</Text>
      <Text style={styles.body}>{truncate(body)}</Text>
    </Pressable>
  );
}

const styles = StyleSheet.create({
  block: {
    backgroundColor: 'white',
    paddingHorizontal: 16,
    paddingVertical: 24,
  },
  date: {
    fontSize: 12,
    color: '#546e7a',
    marginBottom: 8,
  },
  title: {
    color: '#263238',
    fontSize: 18,
    fontWeight: 'bold',
    marginBottom: 8,
  },
  body: {
    color: '#37474f',
    fontSize: 16,
    lineHeight: 21,
  },
});

export default FeedListItem;

 

현재 이유는 모르겠는데 locale: ko를 쓰면 자꾸 오류가 난다..

 

글 작성하다가 이건 왜 나는걸까를 찾을 수가 없다..

 

혹시 아는사람,,

반응형

댓글