Quantcast
Channel: Active questions tagged react-native+typescript - Stack Overflow
Viewing all articles
Browse latest Browse all 6212

React Native Redux-Persist not rehydrating TypeScript class properly

$
0
0

I am working on a React Native (react@~16.9.0) Expo (expo@~37.0.3) Android app that is supposed to store hour registration data locally, for this redux-persist@^6.0.0 is used.

I created a RegistrationWeek domain object that contains all data and some helper functions:

import moment, { Moment } from "moment";import { reset, setRegistrationWeeks, storeConfig, addRegistrationWeek, updateRegistrationWeek } from '../store/register';export class RegistrationDay {  weekDay: string;  date: Moment;  startTime: string;  endTime: string;  break: number;  constructor(weekDay: string, date: Moment, startTime?: string, endTime?: string, breakP?: number) {    this.weekDay = weekDay;    this.date = moment(date);    if (startTime) {      this.startTime = startTime;    } else {      this.startTime = RegistrationWeek.defaultStartTime;    }    if (endTime) {      this.endTime = endTime;    } else {      this.endTime = RegistrationWeek.defaultEndTime;    }    if (breakP) {      this.break = breakP;    } else {      this.break = RegistrationWeek.defaultBreak;    }  }}export default class RegistrationWeek {  static defaultStartTime: string;  static defaultEndTime: string;  static defaultBreak: number;  static store;  weekNumber: number;  startDate: Moment;  endDate: Moment;  year: number;  days: RegistrationDay[];  hours?: number;  constructor(weekNumber: number, startDate: Moment, days?: RegistrationDay[], hours?: number) {    this.weekNumber = weekNumber;    this.startDate = moment(startDate);    this.endDate = moment(startDate).add(6, 'days');    this.year = startDate.isoWeekYear();    if (days) {      this.days = days;    } else {      const tuesday = moment(startDate).add(1, 'day');      const wednesday = moment(startDate).add(2, 'day');      const thursday = moment(startDate).add(3, 'day');      const friday = moment(startDate).add(4, 'day');      this.days = [        new RegistrationDay('Maandag', startDate),        new RegistrationDay('Dinsdag', tuesday),        new RegistrationDay('Woensdag', wednesday),        new RegistrationDay('Donderdag', thursday),        new RegistrationDay('Vrijdag', friday),      ];    }    if (hours) {      this.hours = hours;    }  }  totalTime() {    let returnVal = 0;    this.days.forEach(day => {      const [endH, endM] = day.endTime.split(':');      const [startH, startM] = day.startTime.split(':');      let duration = +endH - +startH;      duration += (+endM - +startM)/60;      duration -= (day.break)/60;      returnVal += duration;    });    return returnVal;  }  dateRange() {    return this.startDate.format('l') +" - "+ this.endDate.format('l');  }  static async storeConfiguration(startTime: string, endTime: string, breakParam: number): Promise<void>  {    RegistrationWeek.defaultStartTime = startTime;    RegistrationWeek.defaultEndTime = endTime;    RegistrationWeek.defaultBreak = breakParam;    storeConfig(RegistrationWeek.store, RegistrationWeek.defaultStartTime, RegistrationWeek.defaultEndTime, RegistrationWeek.defaultBreak);  }  static async init(store?) {    if(store) { RegistrationWeek.store = store };    const register = RegistrationWeek.store.getState().register;    RegistrationWeek.defaultStartTime = register.defaultStartTime;    RegistrationWeek.defaultEndTime = register.defaultEndTime;    RegistrationWeek.defaultBreak = register.defaultBreak;  }  static async save(week: RegistrationWeek): Promise<any> {    return new Promise((resolve) => {      const register = RegistrationWeek.store.getState().register;      const existing = register.registrationData.findIndex(w => w.startDate === week.startDate);      if (existing >= 0) {        updateRegistrationWeek(RegistrationWeek.store, week);      } else {        addRegistrationWeek(RegistrationWeek.store, week);      }      return resolve(week);    });  }  ...  static fetchAllByYear(year: number): Promise<RegistrationWeek[]> {    return new Promise((resolve) => {      const register = RegistrationWeek.store.getState().register;      const returnVal: RegistrationWeek[] = register.registrationData.filter((w: RegistrationWeek) => w.year === year);      console.log(returnVal);      return resolve(returnVal);    });  }}

The register.ts file that has the registrationReducer in it looks as follows:

import RegistrationWeek from "../models/RegistrationWeek";export function reset(store) {  const action = {    type: 'RESET',  }  store.dispatch(action);}export function setRegistrationWeeks(store, registrationData: RegistrationWeek[]) {  const action: {    type: string,    registrationData: RegistrationWeek[],  } = {    type: 'SET_REGISTRATION_WEEKS',    registrationData,  }  store.dispatch(action);}export function addRegistrationWeek(store, week: RegistrationWeek) {  const action: {    type: string,    week: RegistrationWeek,  } = {    type: 'ADD_REGISTRATION_WEEK',    week,  }  store.dispatch(action);}export function updateRegistrationWeek(store, week: RegistrationWeek) {  const action: {    type: string,    week: RegistrationWeek,  } = {    type: 'UPDATE_REGISTRATION_WEEK',    week,  }  store.dispatch(action);}export function storeConfig(store, defaultStartTime: string, defaultEndTime: string, defaultBreak: number) {  const action = {    type: 'STORE_CONFIG',    defaultStartTime,    defaultEndTime,    defaultBreak,  }  store.dispatch(action);}// Initial Stateconst initialState : {  registrationData: RegistrationWeek[],  defaultStartTime: string,  defaultEndTime: string,  defaultBreak: number,} = {  registrationData: [],  defaultStartTime: '9:00',  defaultEndTime: '17:00',  defaultBreak: 30,};// Reducers (Modifies The State And Returns A New State)const registrationReducer = (state = initialState, action) => {  switch (action.type) {    case 'RESET': {      return initialState;    }    case 'SET_REGISTRATION_WEEKS': {      return {        ...state,        registrationData: action.registrationData      };    }    case 'ADD_REGISTRATION_WEEK': {      return {        ...state,        registrationData: [          ...state.registrationData,          action.week,        ],      };    }    case 'UPDATE_REGISTRATION_WEEK': {      const updatedArray: RegistrationWeek[] = [...state.registrationData];      const index = updatedArray.findIndex((w: RegistrationWeek) => w.startDate === action.week.startDate);      updatedArray[index] = action.week;      return {        ...state,        registrationData: updatedArray,      };    }    case 'STORE_CONFIG': {      return {        ...state,        defaultStartTime: action.defaultStartTime,        defaultEndTime: action.defaultEndTime,        defaultBreak: action.defaultBreak,      }    }    default: {      return state;    }  }};export default registrationReducer;

Whenever persisted data gets retrieved after launching the app, it looks like:

Array [  Object {"days": Array [      Object {"break": 30,"date": "2020-04-12T22:00:00.000Z","endTime": "17:00","startTime": "9:00","weekDay": "Maandag",      },      Object {"break": 30,"date": "2020-04-13T22:00:00.000Z","endTime": "17:00","startTime": "9:00","weekDay": "Dinsdag",      },      Object {"break": 30,"date": "2020-04-14T22:00:00.000Z","endTime": "17:00","startTime": "9:00","weekDay": "Woensdag",      },      Object {"break": "20","date": "2020-04-15T22:00:00.000Z","endTime": "17:00","startTime": "9:00","weekDay": "Donderdag",      },      Object {"break": "20","date": "2020-04-16T22:00:00.000Z","endTime": "17:00","startTime": "9:00","weekDay": "Vrijdag",      },    ],"endDate": "2020-04-18T22:00:00.000Z","startDate": "2020-04-12T22:00:00.000Z","weekNumber": 16,"year": 2020,  },]

Instead of the way it looks when saving the data:

Array [  RegistrationWeek {"days": Array [      RegistrationDay {"break": 30,"date": "2020-04-12T22:00:00.000Z","endTime": "17:00","startTime": "9:00","weekDay": "Maandag",      },      RegistrationDay {"break": 30,"date": "2020-04-13T22:00:00.000Z","endTime": "17:00","startTime": "9:00","weekDay": "Dinsdag",      },      RegistrationDay {"break": 30,"date": "2020-04-14T22:00:00.000Z","endTime": "17:00","startTime": "9:00","weekDay": "Woensdag",      },      RegistrationDay {"break": "20","date": "2020-04-15T22:00:00.000Z","endTime": "17:00","startTime": "9:00","weekDay": "Donderdag",      },      RegistrationDay {"break": "20","date": "2020-04-16T22:00:00.000Z","endTime": "17:00","startTime": "9:00","weekDay": "Vrijdag",      },    ],"endDate": "2020-04-18T22:00:00.000Z","startDate": "2020-04-12T22:00:00.000Z","weekNumber": 16,"year": 2020,  },]

It seems like the stored objects get abstracted and the RegistrationWeek constructor is not called these objects.

I tried explicitely calling the constructor when in the init(store? method of the RegistrationWeek class and setting the state property but that did not work:

export class RegistrationDay {  ...  static async init(store?) {    ...    const weeks = register.registrationData.map((w) => { new RegistrationWeek(w.weekNumber, w.startDate, w.days.map((d: RegistrationDay) => { return new RegistrationDay(d.weekDay, d.date, d.startTime, d.endTime, d.break)}))});    setRegistrationWeeks(RegistrationWeek.store, weeks);  }  ...}

Doing this same thing but without setting the objects in the store again does work when it's done as part of a component render function, but the downside with that is that there would be an even bigger mix of templating and data manipulation. The loops would also be repeated every time the component is rendered, which seems like an uneccesarry performance impact to me.

If anyone has any tips, things I missed, on how to deal with this, please let me know!


Viewing all articles
Browse latest Browse all 6212

Trending Articles



<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>