React-Native/[프로젝트] 택시 운행관리 기록장
[React-native CLI] RN에서 Realm 세팅 및 사용(구조 전면 교체)
개발조각
2024. 3. 19. 21:41
728x90
반응형
realm설정을 했었는 데 사용하다 보니 db을 열고 닫는 상황이 중복적으로 발생하다 보니 오류를 마주하게 되고
결국은 realm 구조를 새롭게 수정해보았습니다.
폴더구조
구조는 똑같은데 realm폴더에 recordRealmFunctions.ts를 추가했습니다.
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',
};
realm/recordRealmFunctions.ts
import Realm from 'realm';
import {RecordSchema} from './schema';
import {RecordType} from '../types/types';
// Realm 데이터베이스 연결
const realm = new Realm({schema: [RecordSchema]});
// CREATE : 새로운 기록 추가
export const createRecord = (newData: RecordType) => {
realm.write(() => {
realm.create('Record', newData);
});
console.log('데이터가 생성되었습니다.');
};
// READ_All
export const readAllRecord = () => {
return realm.objects<RecordType>('Record');
};
// READ : 선택한 날짜의 데이터
export const readSelectDateRecord = (selectDate: string) => {
const selectDateData = realm
.objects('Record')
.filtered(`date = '${selectDate}'`)[0];
return selectDateData;
};
// UPDATE
export const updateRecord = (newData: RecordType) => {
const selectDateData = realm
.objects('Record')
.filtered(`date = '${newData.date}'`)[0];
if (selectDateData) {
realm.write(() => {
selectDateData.card = newData.card;
selectDateData.cash = newData.cash;
selectDateData.lpgInjectionVolume = newData.lpgInjectionVolume;
selectDateData.lpgUnitPrice = newData.lpgUnitPrice;
selectDateData.mileage = newData.mileage;
selectDateData.businessDistance = newData.businessDistance;
selectDateData.toll = newData.toll;
selectDateData.operatingAmount = newData.operatingAmount;
selectDateData.lpgChargeAmount = newData.lpgChargeAmount;
selectDateData.fuelEfficiency = newData.fuelEfficiency;
selectDateData.lpgUsage = newData.lpgUsage;
});
console.log('데이터가 수정되었습니다.');
}
};
// DELETE
아직 삭제하기 기능을 넣어주지 않았습니다.
readSelectDateRecord 적용
screens/Record.tsx
// react, react-native
import React, {useCallback, useEffect, useReducer, useState} from 'react';
import {NativeStackScreenProps} from '@react-navigation/native-stack';
// library
// realm
// component
import SubHeader from '../components/record/SubHeader';
import DrivingInfoRecord from '../components/record/DrivingInfoRecord';
import DrivingInfo from '../components/record/DrivingInfo';
import ButtonWrap from '../components/record/ButtonWrap';
// style
import {Record as Style} from '../styles/record.styles';
import * as RecordReducer from '../reducers/recordReducer';
import {readSelectDateRecord} from '../realm/recordRealmFunctions';
type RootStackParamList = {
Profile: {postDate: string};
};
type profileProps = NativeStackScreenProps<RootStackParamList, 'Profile'>;
// 추가하기(+버튼 클릭시), 수정하기(달력에서 날짜 클릭, 수정 클릭)
const Record = ({route}: profileProps) => {
const {postDate} = route.params;
const [selectDate, setSelectDate] = useState(postDate); // 선택한 날짜
const [record, setRecord] = useState(''); // CREATE or UPDATE
const [state, dispatch] = useReducer(
RecordReducer.reducer,
RecordReducer.initialRecord,
);
// selectDate가 realm에 있는지 체크
const readDB = useCallback(() => {
const selectDateData = readSelectDateRecord(selectDate);
if (selectDateData) {
setRecord('UPDATE'); // 데이터 수정
dispatch({type: 'initialize', payload: selectDateData});
} else {
setRecord('CREATE'); // 데이터 생성
const initialData = {...RecordReducer.initialRecord, date: selectDate};
dispatch({type: 'initialize', payload: initialData});
}
}, [selectDate]);
useEffect(() => {
readDB();
}, [readDB, selectDate]);
return (
<Style.container>
{/* 헤더 */}
<SubHeader selectDate={selectDate} setSelectDate={setSelectDate} />
<Style.scrollView>
{/* 기본 운행 정보 기록하기 */}
<DrivingInfoRecord state={state} dispatch={dispatch} />
{/* 운행정보 */}
<DrivingInfo state={state} />
</Style.scrollView>
{/* 취소, 저장 */}
<ButtonWrap record={record} state={state} />
</Style.container>
);
};
export default Record;
CreateRecord, updateRecord 적용
components/record/ButtonWrap.tsx
// realm
import {createRecord, updateRecord} from '../../realm/recordRealmFunctions';
// component
import BasicsButton from '../common/BasicsButton';
// style
import {ButtonWrap as Style} from '../../styles/record.styles';
import {useNavigation} from '@react-navigation/native';
import {RecordType} from '../../types/types';
interface PropsType {
record: string;
state: RecordType;
}
const ButtonWrap = ({record, state}: PropsType) => {
const navigation = useNavigation();
const onGoBackPress = () => {
navigation.goBack();
};
const onSavePress = () => {
if (record === 'CREATE') {
createRecord(state);
} else {
updateRecord(state);
}
navigation.goBack();
};
return (
<Style.container>
<BasicsButton text="취소" option="cancel" onButtonPress={onGoBackPress} />
<BasicsButton text="저장" onButtonPress={onSavePress} />
</Style.container>
);
};
export default ButtonWrap;
readAllRecord 적용
components/common/CalendarView.tsx
// react, react-native
import React, {Dispatch, SetStateAction, useEffect, useState} from 'react';
import {View} from 'react-native';
import {Calendar, LocaleConfig} from 'react-native-calendars';
import {SvgXml} from 'react-native-svg';
// library
import dayjs from 'dayjs';
// assets, realm
import {svg} from '../../assets/svg';
// component
// style
import Theme from '../../styles/Theme';
import {readAllRecord} from '../../realm/recordRealmFunctions';
LocaleConfig.locales['ko'] = {
monthNames: [
'01월',
'02월',
'03월',
'04월',
'05월',
'06월',
'07월',
'08월',
'09월',
'10월',
'11월',
'12월',
],
monthNamesShort: [
'1월',
'2월',
'3월',
'4월',
'5월',
'6월',
'7월',
'8월',
'9월',
'10월',
'11월',
'12월',
],
dayNames: [
'일요일',
'월요일',
'화요일',
'수요일',
'목요일',
'금요일',
'토요일',
],
dayNamesShort: ['일', '월', '화', '수', '목', '금', '토'],
today: '오늘',
};
LocaleConfig.defaultLocale = 'ko';
interface PropsType {
checkDate: string;
setCheckDate: Dispatch<SetStateAction<string>>;
}
const CalendarView = ({checkDate, setCheckDate}: PropsType) => {
// 현재 날짜: 년-월-일
const currentDate = dayjs().format('YYYY-MM-DD');
// realm에서 기록한 날짜 담기
const [markedDate, setMarkedDate] = useState<
Record<string, {marked: boolean}>
>({});
const readMarkedAllDB = () => {
const data = readAllRecord();
const newMarkedDate: Record<string, {marked: true}> = {};
if (data) {
data.forEach(record => {
if (record.date) {
newMarkedDate[record.date] = {marked: true};
}
});
setMarkedDate({...newMarkedDate});
} else {
console.log('데이터가 없습니다.');
}
};
useEffect(() => {
readMarkedAllDB();
}, []);
const markedSelectedDates = {
...markedDate,
[checkDate]: {
selected: true,
marked: markedDate[checkDate]?.marked,
dotColor: Theme.colors.mainDeep,
customStyles: {
container: {
backgroundColor: `${Theme.colors.mainLight}`,
borderRadius: 10,
},
text: {
color: `${Theme.colors.black}`,
},
},
},
};
const customTheme = {
dotColor: '#FF7B00',
// year, month
textSectionTitleColor: `${Theme.colors.black}`,
textSectionTitleDisabledColor: `${Theme.colors.black}`,
// day of week, day
textDayHeaderFontSize: 14,
textDayFontSize: 14,
textDisabledColor: `${Theme.colors.grey}`,
// today
todayTextColor: `${Theme.colors.mainDeep}`,
};
// {"dateString": "2024-03-18", "day": 18, "month": 3, "timestamp": 1710720000000, "year": 2024}
const onDayPress = (day: {dateString: SetStateAction<string>}) => {
setCheckDate(day.dateString);
};
return (
<View>
<Calendar
markingType={'custom'}
markedDates={markedSelectedDates}
onDayPress={onDayPress}
maxDate={currentDate}
theme={customTheme}
monthFormat={'yyyy년 M월'}
renderArrow={direction =>
direction === 'left' ? (
<SvgXml xml={svg.prev} />
) : (
<SvgXml xml={svg.next} />
)
}
/>
</View>
);
};
export default CalendarView;
728x90
반응형