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

[React Native] 3-13 날짜 및 시간 수정 기능 구현하기

by InfoJun 2023. 4. 4.
반응형

이제 로그를 작성할 때,

 

react-native-modal-datetime-picker라는 라이브러리를 사용하여

 

로그의 날짜 및 시간을 수정하는 기능을 구현해보겠습니다.

 

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

이 라이브러리는 Ios와 안드로이드에 각각의 플랫폼에 특화된 날씨/시간 선택 컴포넌트를 제공합니다.

 

이 라이브러리는 네이티브 코드를 사용하기 때문에 시뮬레이터를 재실행해주어야합니다.

 

우선 WriteScreen에서 date 상태를 만들어줍니다.

 

그리고 onSave에서 수정하거나 새로 저장할 때 date 상태를 사용하도록 변경합니다.

 

WriteHeader에는 date와 onChangeDate를 Props로 넣어주겠습니다.

 

screnns/WriteScreen.js

(...)

function WriteScreen({route}) {
  const log = route.params?.log;
  const [title, setTitle] = useState(log?.title ?? '');
  const [body, setBody] = useState(log?.body ?? '');
  const navigation = useNavigation();
  //추가
  const [date, setDate] = useState(log ? new Date(log.date) : new Date());
  // ----
  const {onCreate, onModify, onRemove} = useContext(LogContext);
 (...)
  const onSave = () => {
    console.log(title);
    if (log) {
      onModify({
        id: log.id,
        date: date.toISOString(), // 수정
        title,
        body,
      });
    } else {
      onCreate({
        title,
        body,
        date: date.toISOString(), //  수정
      });
    }
    navigation.goBack();
  };
  return (
    <SafeAreaView style={styles.block}>
      <KeyboardAvoidingView
        style={styles.avoidingView}
        behavior={Platform.OS === 'ios' ? 'padding' : undefined}>
        <WriteHeader
          onSave={onSave}
          onAskRemove={onAskRemove}
          isEditing={!!log}
          //추가
          date={date}
          onChangeDate={setDate}
        />
        <WriteEditor
          title={title}
          body={body}
          onChangeTitle={setTitle}
          onChangeBody={setBody}
        />
      </KeyboardAvoidingView>
    </SafeAreaView>
  );
}

(...)
export default WriteScreen;

 

이 후엔 WriteHeader에서 Pros로 받아온 date를 보여주도록 수정해야 합니다.

 

이는 컴포넌트 중앙에 위치시키겠습니다.

 

position: 'absolute' 속성을 가진 View를 사용해 간단하게 레이아웃을 구성해보겠습니다.

 

conponents/WriteHeader.js

import React from 'react';
import {View, StyleSheet, Pressable, Text} from 'react-native';
import {useNavigation} from '@react-navigation/native';
import TransparentCircleButton from './TransparentCircleButton';
import {format} from 'date-fns';
import {ko} from 'date-fns/locale';

function WriteHeader({onSave, onAskRemove, isEditing, date, onChangeDate}) {
  const navigation = useNavigation();
  const onGoBack = () => {
    navigation.goBack();
  };
  return (
    <View style={styles.block}>
      <View style={styles.iconButtonWrapper}>
        <TransparentCircleButton
          onPress={onGoBack}
          name="arrow-back"
          color={'#424242'}
        />
      </View>
      <View style={styles.buttons}>
        {isEditing && (
          <TransparentCircleButton
            name="delete-forever"
            color={'#ef5350'}
            hasMarginRight
            onPress={onAskRemove}
          />
        )}
        <TransparentCircleButton
          name={'check'}
          color={'#009688'}
          onPress={onSave}
        />
      </View>
      <View style={styles.center}>
        <Pressable>
          <Text>{format(new Date(date), 'PPP', {locale: ko})}</Text>
        </Pressable>
        <View style={styles.separator} />
        <Pressable>
          <Text>{format(new Date(date), 'p', {locale: ko})}</Text>
        </Pressable>
      </View>
    </View>
  );
}

const styles = StyleSheet.create({
  block: {
    height: 48,
    paddingHorizontal: 8,
    flexDirection: 'row',
    alignItems: 'center',
    justifyContent: 'space-between',
  },
  buttons: {
    flexDirection: 'row',
    alignItems: 'center',
  },
  center: {
    position: 'absolute',
    left: 0,
    right: 0,
    top: 0,
    bottom: 0,
    alignItems: 'center',
    justifyContent: 'center',
    zIndex: -1,
    flexDirection: 'row',
  },
  separator: {
    width: 8,
  },
});

export default WriteHeader;

 

center 스타일에서 position : 'absoulte'를 설정하고 모든 값을 0으로 설정했습니다.

 

이는 컴포넌트의 상위 컴포넌트 크기만큼 꽉 채우겠다는 의미입니다.

 

zIndex라는 속성은 컴포넌트가 다른 컴포넌트와 위치가 중첩될 때 앞 레이어에 나타날지

 

뒤 레이어에 나타날지 경정하는 값인데, 기본적으로 높은 값이 더 낮은 값을 가진 컴포넌트를 가립니다.

 

이제는 날짜 또는 시간을 누르면 DateTimePickerModal 컴포넌트를 보여줘서

 

날짜를 수정할 수 있게 만들어보겠습니다.

 

사용법은 다음과 같습니다.

 

<DateTimePickerModal
	onConfirm={onConfirm}
    onCancel={onCancel}
    mode={mode}
    date={date}
    isVisivle={visible}
/>
  • onConfirm : 날짜를 선택했을 때 호출되는 함수입니다. 함수의 파라미터는 Date 객체입니다.
  • onCancel :  날짜 선택을 취소했을 때 호출되는 함수입니다.
  • mode : 모달의 모드를 설정합니다. 설정할 수 있는 값은 date, time, datetime입니다.
  • date : 컴포넌트에서 보여졌을 때 초깃값으로 설정할 Date 객체 타입의 값입니다.
  • isVisible: 이 값을 true로 설정하면 모달이 보이고, false로 설정하면 모달이 사라집니다

날짜를 눌렀을 때는 'date' 모드, 시간을 선택했을 때는 'time'모드를 사용하겠습니다.

 

components/WriteHeader.js

import React, {useState} from 'react';
import {View, StyleSheet, Pressable, Text} from 'react-native';
import {useNavigation} from '@react-navigation/native';
import TransparentCircleButton from './TransparentCircleButton';
import {format} from 'date-fns';
import {ko} from 'date-fns/locale';
import DateTimePickerModal from 'react-native-modal-datetime-picker';

function WriteHeader({onSave, onAskRemove, isEditing, date, onChangeDate}) {
(...)

  //추가
  const [mode, setMode] = useState('date');
  const [visible, setVisible] = useState(false);

  const onPressDate = () => {
    setMode('date');
    setVisible(true);
  };

  const onPressTime = () => {
    setMode('time');
    setVisible(true);
  };

  const onConfirm = selectedDate => {
    setVisible(false);
    onChangeDate(selectedDate);
  };

  const onCancel = () => {
    setVisible(false);
  };

  //-----

  return (
    (...)
      <View style={styles.center}>
        <Pressable onPress={onPressDate}>
          <Text>{format(new Date(date), 'PPP', {locale: ko})}</Text>
        </Pressable>
        <View style={styles.separator} />
        <Pressable onPress={onPressTime}>
          <Text>{format(new Date(date), 'p', {locale: ko})}</Text>
        </Pressable>
      </View>
      <DateTimePickerModal
        isVisible={visible}
        mode={mode}
        onConfirm={onConfirm}
        onCancel={onCancel}
        date={date}
      />
    </View>
  );
}

(...)

 

반영이 잘 되나요?

반응형

댓글