개발조각

[React-native CLI] RN 기록화면 구현하기 1부 (선택한 날짜에 따라 Creact, Update하기) 본문

React-Native/[프로젝트] 택시 운행관리 기록장

[React-native CLI] RN 기록화면 구현하기 1부 (선택한 날짜에 따라 Creact, Update하기)

개발조각 2024. 3. 18. 14:21
728x90
반응형

+버튼을 클릭하면 현재날짜의 데이터에서 운행정보를 기록할 수 있도록

달력에서 다른 날짜를 선택하면 선택한 날짜의 데이터로 기록 운행 정보 기록할 수 있도록 구현하기

 

그리고 기본 운행 정보 기록하기에서 카드, 현금, LPG 주입량, LPG 단가, 주행거리, 영업거리, 통행료를 입력하면

기본 운행 정보 기록하기에 기록한 값을 가지고 운행 정보를 출력하는 화면을 만들 예정입니다.

(이건 아마 2부에서 설명할 것 같습니다.)

 

구현 화면

기록화면 생성하기, 수정하기를 같은 화면에 보여줄 예정입니다.

(새로운 기록장 생성할때도 Record.tsx, 기존 기록장 수정할 때도 Record.tsx로 )

 

+버튼을 클릭하면 현재날짜의 데이터에서 운행정보를 기록 할 수 있도록, 달력에서 다른 날짜를 선택하면 선택한 날짜의 데이터로 기록 운행 정보 기록할 수 있도록 구현하기


 

순서

1. Home.tsx에서 +버튼은 클릭하면 현재날짜 Record.tsx에 현재 날짜를 전달해 준다.

(만약 오늘이 2024년 3월 18일이면 2024-03-18을 보내준다.)

2. 선택한 날짜에 따라 현재 날짜가 realm에 데이터가 있는지 확인하기

  • +버튼을 클릭하면 현재 날짜가 realm에서 해당날짜의 데이터가 있는지 확인하기
  • 달력 모달페이지에서 선택한 날짜에 따라 realm에 해당날짜의 데이터가 있는지 확인하기

 

1. Home.tsx에서 +버튼은 클릭하면 현재날짜 Record.tsx에 현재 날짜를 전달하기


Home.tsx에서 +클릭 시 현재 날짜 보내기

components/home/CreateButton.tsx

// react, react-native
import {View} from 'react-native';
import {useNavigation} from '@react-navigation/native';
import {SvgXml} from 'react-native-svg';

// library

// assets, utils, realm
import {svg} from '../../assets/svg';

// component

// style
import {CreateButton as Style} from '../../styles/home.styles';

interface PropsType {
  currentDate: string;
}

const CreateButton = ({currentDate}: PropsType) => {
  const navigation = useNavigation();

  const onNavigationPress = () => {
    navigation.navigate('Record', {postDate: currentDate});
  };

  return (
    <Style.button onPress={onNavigationPress}>
      <View>
        <SvgXml xml={svg.plus} fill="#FFA800" />
      </View>
    </Style.button>
  );
};

export default CreateButton;

 

주요 코드

const onNavigationPress = () => {
    navigation.navigate('Record', {postDate: currentDate});
  };

 

 

계속 이 부분에서 에러가 발생하는데 이건 수정되면 추가로 작성하겠습니다.

'Record', {postDate: currentDate}

 

 

Record.tsx에서 Home스크린에서 +버튼을 클릭하면 현재 날짜를 가지고 오기

screens/Record.tsx

import {NativeStackScreenProps} from '@react-navigation/native-stack';

// 네비게이션 스택에 해당하는 파라미터 타입 정의
type RootStackParamList = {
  Profile: {postDate: string};
};

// 네비게이션 스택의 네비게이션 프롭스 및 라우트 프롭스를 제공하는 컴포넌트의 프롭스 타입 정의
type profileProps = NativeStackScreenProps<RootStackParamList, 'Profile'>;

const Record = ({route}: profileProps) => {
  const {postDate} = route.params;
  console.log('+버튼에서 전달받은 날짜:', postDate);
  ...
}

 

타입 지정 안 해주면 route에서 계속 오류가 나서 타입지정해 주었습니다.

아래 링크를 참고하여 타입을 설정해주었습니다.

https://reactnavigation.org/docs/typescript/

 

Type checking with TypeScript | React Navigation

React Navigation is written with TypeScript and exports type definitions for TypeScript projects.

reactnavigation.org

 

2. 선택한 날짜에 따라 현재 날짜가 realm에 데이터가 있는지 확인하기


realm설정하기

realm.schema.ts

// 운행기록 스키마
export const RecordSchema = {
  name: 'Record',
  properties: {
    date: 'string', // 날짜는 문자열로 저장할 수 있습니다.
    // 기본값을 지정할 수 있습니다.
    card: 'int',
    cash: 'int', // 현금
    lpgInjectionVolume: 'int', // LPG 주입량
    lpgUnitPrice: 'int', // LPG 단가
    mileage: 'int', // 주행거리
    businessDistance: 'int', // 영업거리
    toll: 'int', // 통행료
    operatingAmount: 'int', // 영업금액
    lpgChargeAmount: 'int', // LPG 충전 금액
    fuelEfficiency: 'int', // 연비
    lpgUsage: 'int', // LPG 사용량
  },
  primaryKey: 'date',
};

 

screens/Record.tsx

// react, react-native
import {useCallback, useEffect, useRef, useState} from 'react';
import {NativeStackScreenProps} from '@react-navigation/native-stack';

// library
import Realm from 'realm';

// assets, utils, realm
import {RecordSchema} from '../realm/schema';

// 네비게이션 스택에 해당하는 파라미터 타입 정의
type RootStackParamList = {
  Profile: {postDate: string};
};

// 네비게이션 스택의 네비게이션 프롭스 및 라우트 프롭스를 제공하는 컴포넌트의 프롭스 타입 정의
type profileProps = NativeStackScreenProps<RootStackParamList, 'Profile'>;

const Record = ({route}: profileProps) => {
  const {postDate} = route.params;
  const realm = useRef<Realm>();
  
  const [selectDate, setSelectDate] = useState(postDate); // 선택한 날짜
  const [record, setRecord] = useState('');

  
  // selectDate가 realm에 있는지 체크
  const readDB = useCallback(() => {
    const selectDateData = realm.current
      ?.objects('Record')
      .filtered(`date = '${selectDate}'`)[0];

    if (selectDateData) {
      setRecord('UPDATE'); // 데이터 수정
      console.log('데이터가 있습니다.', selectDateData);
    } else {
      setRecord('CREATE'); // 데이터 생성
      console.log(데이터가 없습니다.);
    }
  }, [selectDate]);
  
  // selectDate가 변경되면 readDB()렌더링
  useEffect(() => {
    readDB();
  }, [readDB, selectDate]);

  const openLocalDB = async () => {
    realm.current = await Realm.open({schema: [RecordSchema]});
    console.log('realmDB 열기!');

    readDB();
  };

  // realmDB 열기, 닫기
  useEffect(() => {
    openLocalDB();

    return () => {
      realm.current?.close();
      console.log('realmDB 닫기!');
    };
  }, []);
}

 

realm 사용방법에 대해서는 아래 블로그를 확인하시면 됩니다.

https://development-piece.tistory.com/440

 

[React-native CLI] Realm 사용하기 및 사용방법

드디어 Realm을 설치할 시간이 왔습니다. expo프로젝트를 버리고 cli로 다시 한 이유 중 하나가 realm이기도 하죠ㅎㅎ 참고 블로그 https://velog.io/@ddowoo/react-native-local-Database-Realm-DB react native 에서 local D

development-piece.tistory.com

 

useCallback사용한 이유에 대해서는 아래 블로그를 확인하시면 됩니다.

https://development-piece.tistory.com/446

 

[React-native CLI] RN에서 useCallback 사용 (useEffect 의존성 배열 오류 발생 해결)

이번에 프로젝트 작업을 하면서 useCallback을 사용하게 되었습니다. useCallback이란 useCallback hook은 메모이제이션된 콜백 함수를 생성하는 데 사용됩니다. 일반적으로 컴포넌트에서 함수를 정의할

development-piece.tistory.com

 

주요 코드

  // selectDate가 realm에 있는지 체크
  const readDB = useCallback(() => {
    // selectDate에 해당하는 데이터만 추출
    const selectDateData = realm.current
      ?.objects('Record')
      .filtered(`date = '${selectDate}'`)[0];

    if (selectDateData) {
      setRecord('UPDATE'); // 데이터 수정
      console.log('데이터가 있습니다.', selectDateData);
    } else {
      setRecord('CREATE'); // 데이터 생성
      console.log(데이터가 없습니다.);
    }
  }, [selectDate]);

 

여기서 selectDateData에 [0]을 해준 이유는 [0]을 안 해주면

// 이렇게만 한다면
const selectDateData = realm.current
      ?.objects('Record')
      .filtered(`date = '${selectDate}'`);

selectDateData가 있을 경우 [{data: 'selecDate에 해당하는 날짜',...}]가 나오고, selectDateData가 없을 경우 []가 나오기 때문에 [0]을 해주었습니다.

 

제가 이전에 schema를 작성할 때 primarykey: 'date'로 설정했기 때문에 어떤 selectDate를 넣더라고 selectDateData는 [{data: 'selecDate에 해당하는 날짜',...}]아니면 []만 나오게 됩니다.

그래서 [0]을 써주었습니다.

 

selectDateData가 있다는 말은 데이터 수정을 의미하기 때문에 UPDATE로 표시해 주고

setRecord('UPDATE');

 

selectDateData가 없다는 말은 데이터를 새로 생성한다는 의미이기 때문에 CREATE로 표시해 주었습니다.

setRecord('CREATE');

 

데이터가 없을 경우 / 있을 경우

 

 

입력한 데이터에 따라 create 하거나, update 하는 기능은 다음 글에 useReducer로 입력데이터 구현설명과 함께 올리겠습니다.

728x90
반응형
Comments