본문 바로가기

webOS

webOS: web app 개발일지(4)

react life cycle에 대해 간단히 정리했다.

https://projects.wojtekmaj.pl/react-lifecycle-methods-diagram/

 

https://staminaloops.github.io/undefinedisnotafunction/understanding-react/

  • mount : 처음 render되고 component 생성 및 DOM 적용
    • constructor() / static getDerivedStateFromProps() / render() / componentDidMount()
  • update : props, state re-render
    • static getDerivedStateFromProps() / shouldComponentUpdate() / render() / getSnapshotBeforeUpdate() / componentDidUpdate()
  • unmount : component DOM 제거
    • componentWillUnmount()

 

 

 

Calendar.js를 마저 살펴보자.

 

1) import

import {Component} from 'react';	// for using react component class
import moment from 'moment';	// use moment.js lib for calendar
import Dialog from '@enact/moonstone/Dialog';	
import Scroller from '@enact/moonstone/Scroller';
import Notification from '@enact/moonstone/Notification';	// use specific moonstone lib

import './calendar.css';
import {dbServices} from '../../services/dbServices';
import {generateQuery} from '../../services/generateQuery';
import CreateForm from '../CreateForm/CreateForm';
import Days from './Days';
import CalendarHeader from './CalendarHeader';
import EventsList from '../EventsList/EventsList';	// import js from specific folder
import Button from '@enact/moonstone/Button';
import Header from "./Header";
const _kind = 'com.reference.app.service.familyeventplanner:4';

딱히 특별한 건 없고, moonstone lib에서 api를 받아오거나 다른 js 파일을 호출한다.

다만 날짜 관련 기능을 사용하기 위해 moment.js를 import 했다.

 

2) calendar

export default class Calendar extends Component {
    state = {	// initial state
     dateContext: moment(),
     today: moment(),	// to get current date and time
     selectedDay: null,
     dailog : false,	//
     dailogSubTitle: null,
     monthsData : [],	//
     notification: false,
     notificationMsg: '',
     dailogType: 'form'	//
    };

    constructor (props) {	// component class constructor
     super(props);
     this.width = props.width || '100%';	// inital state - width, style
     this.style = props.style || {};
     this.style.width = '100%';
    }

    componentDidMount () {	// invoked after a component is mounted
     dbServices.createKind((resp) => { // dbServices.js
      console.log('Response in callback :: ', resp);
      if (resp.returnValue) {
       this.getDataFromDb();
      }
     });
    }

    getDataFromDb = () => {
     let month = this.months.indexOf(this.month()) + 1;
     let query = generateQuery.findQuery({ // generateQuery.js
      'year': this.year(),
      'month': month.toString()
     });
     console.log('Query here :: ', query);
     dbServices.findData(query, (res) => {
      console.log('Find data response :: ', res);
      if (res.returnValue) {
       let monthsData = generateQuery.filterData(res.results);
       console.log('This month data here :: ', monthsData);
       this.setState({monthsData});
      }
     });
    };
  • state : defines local state, object default state를 설정
  • constructor() : defines local state / binds event handler, props에 의해 결정
  • componentDidMount() : DOM mount 이후 re-render
    • dbServices.createKind()
import LS2Request from '@enact/webos/LS2Request';	// use LS2 API

export const dbServices = {
 createKind : (cb) => {
  return new LS2Request().send({	// send a request to an LS2 service method
   service: 'luna://com.webos.service.db',	// the name of the LS2 service
   method: 'putKind',
   parameters: {
    'id':'com.reference.app.service.familyeventplanner:4',
    'owner':'com.reference.app.familyeventplanner',
    'indexes':[
     {'name':'year', 'props':[{'name':'year'}]},
     {'name':'month', 'props':[{'name':'month'}]},
     {'name':'date', 'props':[{'name':'date'}]},
     {'name':'fullDate', 'props':[{'name':'year'}, {'name':'month'}, {'name':'date'}]}
    ]	// required parameters by the service method
   },
   onSuccess: (res) => {	// success handler
    console.log('Success response :: ', res);
    cb(res);
   },
   onFailure: (res) => {	// failure handler
    console.log('Failed response :: ', res);
    cb(res);
   }
  });
 },

일단 import 문으로 enact에서 webos LS2 API를 사용할 수 있도록 처리해야 한다. 이후 createKind 함수를 선언하는데 이를 위해 db를 사용해야 하므로 LS2 API 중 com.webos.service.db에 접근하여 putKind 함수를 요청한다. 그리고 putKind 함수에 필요한 parameter를 전달한다.

id, owner, indexes를 지정한다. 여기서는 year, month, date, fullDate의 네 가지를 만들었다.

그리고 성공 / 실패할 경우의 event handler를 지정한다.

 

  • getDataFromDb()
    • generateQuery.js
export const generateQuery = {
 findQuery : (obj) => {
  let query = {
   'from':_kind,
   'where':[]
  };
  for (let key in obj) {
   query['where'].push({
    'prop' : key,
    'op': '=',
    'val': obj[key]
   });
  }
  return query;
 },

createKind가 성공했을 시 getDataFromDb() 함수가 실행된다.

month는 이번 달의 str과 각 개월의 str을 비교하여 index를 구한 값이다.

generateQuery.findQuery를 보면, 'year'과 'month' data를 넘겨 query에 push하고 있다.

 

  • dbServices.findData(query, (res))
 findData : (queryObj, cb) => {
  return new LS2Request().send({
   service: 'luna://com.webos.service.db',
   method: 'find',
   parameters: {
    'query': queryObj
   },
   onSuccess: (res) => {
    console.log('Success response :: ', res);
    cb(res);
   },
   onFailure: (res) => {
    console.log('Failed response :: ', res);
    cb(res);
   }
  });
 }

 

find를 위해 다시 한번 LS2Request.send하여 db의 find method를 사용한다. 마찬가지로 'year', 'month'의 query를 parameter로 사용한다. 성공할 시 generateQuery.filterData를 실행한다.

 

이후 setState()을 실행하는데, react에서 setState는 기존 state를 변경시키고 re-render한다.

 

  • generateQuery.filterData
 filterData : (arr) => {
  let filteredData = {};

  for (let i = 0; i < arr.length; i++) {
   if (!filteredData[arr[i].year]) {
    filteredData[arr[i].year] = {};
   }

   if (!filteredData[arr[i].year][arr[i].month]) {
    filteredData[arr[i].year][arr[i].month] = {};
   }

   if (!filteredData[arr[i].year][arr[i].month][arr[i].date]) {
    filteredData[arr[i].year][arr[i].month][arr[i].date] = [];
   }

   let temp = {};
   temp['title'] = arr[i]['event']['title'];
   temp['description'] = arr[i]['event']['description'];
   temp['image'] = arr[i]['image'];

   filteredData[arr[i].year][arr[i].month][arr[i].date].push(temp);
  }

  return filteredData;
 }

data를 적절히 filter하여 return한다.

 

 

    weekdays = moment.weekdays(); // ["Sunday", "Monday", "Tuesday", "Wednessday", "Thursday", "Friday", "Saturday"]
    weekdaysShort = moment.weekdaysShort(); // ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"]
    months = moment.months(); // ['January', 'February', 'March', 'April', 'September', 'October', 'November', 'December']

    year = () => {
     return this.state.dateContext.format('Y');	// 2022
    };
    month = () => {
     return this.state.dateContext.format('MMMM'); // August
    };
    daysInMonth = () => {
     return this.state.dateContext.daysInMonth(); // 31
    };
    currentDate = () => {
     return this.state.dateContext.get('date');	// moment
    };
    currentDay = () => {
     return this.state.dateContext.format('D'); // 28
    };
    
    firstDayOfMonth = () => {
     let dateContext = this.state.dateContext;
     let firstDay = moment(dateContext).startOf('month').format('d'); // Day of week 0...1..5...6
     return firstDay;
    };

다음은 moment의 data를 가져오는 과정이다. 위와 같이 moment.js를 활용하여 필요한 data로 변환한다.

 

    setDateContext = (dateContext) => {
     this.setState({
      dateContext: dateContext
     }, () => {
      this.getDataFromDb();
     });
    };

    setMonth = (month) => {
     let monthNo = this.months.indexOf(month);
     let dateContext = Object.assign({}, this.state.dateContext);
     dateContext = moment(dateContext).set('month', monthNo);
     this.setDateContext(dateContext);
    };

    nextMonth = () => {
     let dateContext = Object.assign({}, this.state.dateContext);
     dateContext = moment(dateContext).add(1, 'month');
     this.setDateContext(dateContext);
     this.props.onNextMonth && this.props.onNextMonth();
    };

    prevMonth = () => {
     let dateContext = Object.assign({}, this.state.dateContext);
     dateContext = moment(dateContext).subtract(1, 'month');
     this.setDateContext(dateContext);
     this.props.onPrevMonth && this.props.onPrevMonth();
    };

setDateConext가 setState와 getDataFromDb()로 dateContext를 재설정하고 db에 저장, 조회한다.

setMonth는 인수로 들어온 month로 dataContext를 수정하고 갱신한다. nextMonth, prevMonth는 dataContext를 복사하고 이전, 이후의 month 값을 setDateContext한다.

 

event listener부터는 다음 포스팅에 계속 살펴보겠다.

 

 

 

'webOS' 카테고리의 다른 글

webOS: web app 개발일지(5)  (0) 2022.10.06
webOS: web app 개발일지(3)  (0) 2022.09.29
webOS: web app 개발일지(2)  (0) 2022.09.28
webOS: web app 개발일지(1)  (0) 2022.09.19
# JavaScript  (0) 2022.08.23