[React Native] 유용한 기능들

seongminn·2022년 8월 31일

React Native

목록 보기
2/2
post-thumbnail

date-fns

게시물을 포스팅 할 때, 게시물 작성 시간이 얼마나 지났는가에 따라 시간 표시 형식을 다르게 해주는 라이브러리

설치

$ yarn add date-fns

사용
formatDistanceToNow - 현재 시각을 기준으로 단어를 사용해 시간을 나타낸다. (예: 5분 전)
format - 다양한 형태로 날짜를 포맷팅한다.
• 그 외의 기능들은 여기를 참조

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) {
    // addSuffix - 포맷팅된 문자열 뒤에 ‘전’ 또는 ‘후’ 접미사를 붙이는 옵션
    // locale - 언어. 문자열이 아니라 'date-fns/locale'에서 불러온 객체임에 주의할 것
    return formatDistanceToNow(d, {addSuffix: true, locale: ko});
  }
  
  // PPP - 날짜, EEE - 요일, p - 시간
  return format(d, 'PPP EEE p', {locale: ko});
}

Animated

애니메이션 기능을 적용한다.

사용
react-native에 내장되어 있는 {Animated} 객체를 활용한다. 객체 생성 시에는 useRef() 함수를 사용하여 특정 값을 설정해준다. 이제 컴포넌트가 사라질 때까지 해당 객체를 재사용할 수 있다.

이제 Animation.View와 같이 애니메이션 효과를 주고 싶은 컴포넌트의 이름 앞에 Animation.을 붙여서 사용할 수 있다.

애니메이션 효과의 스타일을 설정하고 싶을 때는 Animation.timing()이라는 함수를 사용한다.

Animated.timing(animation, {
  toValue: 0, // 어떤 값으로 변경할지 - 필수
  duration: 1000, // 애니메이션에 걸리는 시간(밀리세컨드) - 기본값: 500
  delay: 0, // 딜레이 이후 애니메이션 시작 - 기본값: 0
  useNativeDriver: true, // 네이티브 드라이버, 레이아웃과 관련없는 스타일에만 적용 가능 - 필수
  isInteraction: true, // 사용자 인터랙션에 의해 시작한 애니메이션인지 지정 - 기본값: true
  // 애니메이션 속도 변경 함수 - 기본값: Easing.inOut(Easing.ease)
  easing: Easing.inOut(Easing.ease), 
}).start(() => {
  // 애니메이션 처리 완료 후 실행할 작업
})

참고로 timing() 대신 Animation.spring()을 사용하게 되면, 마치 스프링이 통통 튀는 것과 같은 조금 더 역동적인 애니메이션을 연출할 수 있다.

Spring() 함수에는 다음과 같은 속성을 지정할 수 있으니 참고하자.
tension: 강도(기본값: 40)
friction: 감속(기본값: 7)
speed: 속도(기본값: 12)
bounciness: 탄력성(기본값: 8)

animation.interpolate()
value가 갖고 있는 값을 기준으로 새로운 값을 생성할 수 있다.

// 예시
animation.interpolate({
  inputRange: [0, 1],
  outputRange: [0, 150],
})

위와 같은 경우에, value값이 0일 경우 출력값이 0으로, 1인 경우 출력값이 150으로 지정된다.

// 예시
// importing..

function AnimationPractice() {
  const animation = useRef(new Animated.Value(1)).current;
  const [enabled, setEnabled] = useState(false);

  useEffect(() => {
    Animated.timing(animation, {
      toValue: enabled ? 1 : 0,
      useNativeDriver: true,
    }).start();
  }, [enabled, animation]);

  return (
	<View>
	  <Animated.View
	    style={[
	      styles.rectangle,
	      {
	        transform: [
	          {
	            translateX: animation.interpolate({
                  // input이 0일 때 translateX값이 0, 1일 때 150
	              inputRange: [0, 1],
	              outputRange: [0, 150],
	            }),
	          },
	        ],
	        opacity: animation.interpolate({
              // input이 0일 때 opacity가 1, 1일 때 0
	          inputRange: [0, 1],
	          outputRange: [1, 0],
	        }),
	      },
	    ]}
	  />
	  <Button title="Toggle" onPress={() => setEnabled(!enabled)} />
	</View>
  )
}

FlatList

onEndReached, onEndReachedThreshold
FlatList 컴포넌트의 items 중 끝부분에 가까워졌을 때 특정 함수를 호출하고자 한다면 onEndReached, onEndReachedThreshold를 사용할 수 있다.

<FlatList
  (...)
  onEndReached={(distanceFormEnd) => {
    console.log('바닥과 가까워졌어요!');
  }}
  // 85%까지 스크롤 했을 때 onEndReached 함수 호출
  onEndReachedThreshold={0.85}
/>

한계
해당 속성은 스크롤이 특정 수치에 도달했을 때 함수를 호출하는 기능은 보유하고 있지만, 스크롤이 멀어지는 것을 구분하지는 못한다.

그래서 onScroll 함수를 활용하여 해당 기능을 구현하는 방법을 추천한다.

function FeedList({logs}) {
  const onScroll = e => {
    const {contentSize, layoutMeasurement, contentOffset} = e.nativeEvent;
    console.log({contentSize, layoutMeasurement,contentOffset});
  };
  return (
    <FlatList
      data={logs}
      style={styles.block}
      renderItem={({item}) => <FeedListItem log={item} />}
      keyExtractor={log => log.id}
      ItemSeparatorComponent={() => <View style={styles.separator} />}
      onScroll={onScroll}
    />
  );
}

이 때, contentSize.heightFlatList 내부의 전체 크기, layoutMeasurement.height는 화면에 나타난 FlatList의 실제 크기를 나타낸다. contentOffset.y는 스크롤이 가장 위에 있을 때 0이고, 가장 아래에 있을 때는 contentSize.height - layoutMeasurement.height을 계산한 값이다.

따라서 contentSize.height - layoutMeasurement.height - contentOffset.y가 0에 가까울수록 FlatList의 가장 끝 항목에 가까워지는 것이다.

ListHeaderComponent
데이터를 받아와 출력하고자 하는 컴포넌트 위에 보여준다.

function CalendarScreen() {
  const {logs} = useContext(LogContext);
  const [selectedDate, setSelectedDate] = useState(
    format(new Date(), 'yyyy-MM-dd'),
  );

  const markedDates = logs.reduce((acc, current) => {
    const formattedDate = format(new Date(current.date), 'yyyy-MM-dd');
    acc[formattedDate] = {marked: true};
    return acc;
  }, {});

  const filteredLogs = logs.filter(
    log => format(new Date(log.date), 'yyyy-MM-dd') === selectedDate,
  );

  return (
    <FeedList
      logs={filteredLogs}
      // CalendarView 컴포넌트를 FeedList 위에 보여준다.
      ListHeaderComponent={
        <CalendarView
          markedDates={markedDates}
          selectedDate={selectedDate}
          onSelectDate={setSelectedDate}
        />
      }
    />
  );
}

Array 함수

Array.some()
원하는 조건을 인자로 넣어주면 배열 내에서 해당 조건에 부합하는 값이 하나라도 있을 때 true를 반환하고, 그렇지 않은 경우에는 false를 반환한다.

const filtered =
  keyword === ''
    ? []
    : logs.filter(log =>
		// title과 body 중 keyword를 포함한 것이 있다면 true, 그렇지 않다면 false 반환
        [log.title, log.body].some(text => text.includes(keyword)),
      );

Array.reduce()
배열을 기반으로 하나의 값을 얻고자 할 때 사용할 수 있다. 다음과 같은 인수를 받는다.

accumulator – 이전 함수 호출의 결과. initial은 함수 최초 호출 시 사용되는 초깃값을 나타냄(옵션)
item – 현재 배열 요소
index – 요소의 위치
array – 배열

다음 예제를 통해 살펴보도록 하자.

arr = [1, 2, 3, 4, 5]
const value = arr.reduce((sum, current) => sum + current, 0)

console.log(value) // 15

함수 최초 호출 시 reduce에 전달한 함수의 마지막 인자인 0이 sum에 할당된다. 그리고 current에는 배열의 첫 번째 요소가 할당되어 함수의 결과는 1이 된다. 그 다음에는 결과값인 1이 sum에 할당이 되고 current는 2가 되어 결국 3이 반환된다. 이를 배열의 모든 요소에 적용하여 결국 15가 반환된다.

비슷한 메서드로 Arr.reduceRight()가 있는데, 이는 배열의 오른쪽에서부터 연산을 실행한다는 차이점이 있다.


React Native Calendars

react native에서 달력을 만들 수 있게 도와주는 라이브러리

설치

$ yarn add react-native-calendars

사용
react-native-calendars 라이브러리에서 Calendar 컴포넌트를 불러와주기만 하면 된다.

그리고 markedDates 속성을 사용하면 특정 날짜에 몇가지 표시를 할 수 있는데 이 객체에는 yyyy-MM-dd 형식의 날짜를 입력할 수 있다. 이 때, marked 값을 true로 설정하게 되면 점이 표시되고, selected의 값을 true로 설정하면 해당 날짜의 배경색을 변경한다. 이 때 표시 색상은 theme props를 통해 변경할 수 있다.

Calendar 컴포넌트에 onDayPress 함수를 이용하면 특정 날짜를 눌렀을 때 함수를 실행할 수 있다. 해당 함수에서는 day 객체를 인자로 넘겨줄 수 있는데, 다음과 같이 구성되어 있다.

{
  "dateString": "2021-08-23", 
  "day": 23, 
  "month": 8, 
  "timestamp": 1629676800000, 
  "year": 2021
}

react-native-modal-datetime-picker

@react-native-community/datetimepickeriOSandroid 각각 플랫폼에 특화된 날짜, 시간 선택 컴포넌트를 제공하고 react-native-modal-datetime-picker는 날짜, 시간 선택 컴포넌트를 모달 형태로 쉽게 사용할 수 있게 해준다.

설치

$ yarn add react-native-modal-datetime-picker @react-native-community/datetimepicker

DateTimePicker

function Practice() {
  return (
    <DateTimePickerModal
      onConfirm={onConfirm}
      onCancel={onCancel}
      mode={mode}
      date={date}
      isVisible={visible}
    />
  )
}

onConfirm: 날짜를 선택했을 때 호출되는 함수로, 이 함수의 파라미터는 Date 객체이다.
onCancel: 날짜 선택을 취소했을 때 호출되는 함수
mode: 모달의 모드를 설정한다. 설정할 수 있는 값은 date, time, datetime이다.
date: 컴포넌트에서 보여졌을 때 초깃값으로 설정할 Date 객체 타입의 값이다.
isVisible: 해당 값을 true로 설정하면 모달이 보이고, false로 설정하면 모달이 사라진다.

profile
돌멩이도 개발 할 수 있다

0개의 댓글