Реакция Native Redux-Persist не вызывает трансформатор на регидрат - PullRequest
1 голос
/ 26 апреля 2020

Я работаю над приложением React Native (react@~16.9.0) Expo (expo@~37.0.3) Android, которое должно хранить данные о регистрации за час локально, для этого используется redux-persist@^6.0.0.

I создал RegistrationWeek объект домена, содержащий все данные и некоторые вспомогательные функции:

import moment, { Moment } from "moment";
import { ..., addRegistrationWeek, updateRegistrationWeek } from '../store/register';

export class RegistrationDay {
  ...

  constructor(...) {
    ...
  }
}

export default class RegistrationWeek {
  ...

  constructor(...) {
    ...
  }

  totalTime() {
    ...
  }

  dateRange() {
    ...
  }

  ...

  static init(store?) {
    if(store) { RegistrationWeek.store = store };
    const register = RegistrationWeek.store.getState().register;
    ...
  }

  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);
    });
  }

  ...

}

Файл register.ts, содержащий registrationReducer, выглядит следующим образом:

import RegistrationWeek from "../models/RegistrationWeek";

...

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);
}

...

// Initial State
const initialState : {
  registrationData: RegistrationWeek[],
  ...
} = {
  registrationData: [],
  ...
};
// Reducers (Modifies The State And Returns A New State)
const registrationReducer = (state = initialState, action) => {
  switch (action.type) {
    ...
    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,
      };
    }
    default: {
      return state;
    }
  }
};
export default registrationReducer;

Этот registrationReducer настроен и включен в rootReducer вместе с Transformer:

// Imports: Dependencies
import { combineReducers } from 'redux';
// Imports: Reducers
import registerReducer from './register';
import { persistReducer } from 'redux-persist';
import { AsyncStorage } from 'react-native';
import Transformer from './transformer';

const registerPersistConfig = {
  key: 'register',
  storage: AsyncStorage,
  transformers: [Transformer],
  whitelist: ['registrationData', ...],
  blacklist: [],
};

// Redux: Root Reducer
const rootReducer = combineReducers({
  register: persistReducer(registerPersistConfig, registerReducer),
});
export default rootReducer;

Transformer выглядит следующим образом:

import { createTransform, TransformInbound, TransformOutbound } from 'redux-persist';

import RegistrationWeek, { RegistrationDay } from '../models/RegistrationWeek';

interface State {
  registrationData: RegistrationWeek[],
  ...
}

const Transformer = createTransform<State, State, any, any>(
  // transform state on its way to being serialized and persisted.
  (inboundState: State, key) => {
    return { ...inboundState };
  },

  // transform state being rehydrated
  (outboundState: State, key) => {
    return {
      registrationData: outboundState.registrationData.map((w: RegistrationWeek) => {
        new RegistrationWeek(..., w.days.map((d: RegistrationDay) => {
            return new RegistrationDay(...)
      }))}),
      ...outboundState,
    }
  },

  { whitelist: ['registrationData'] }
);

export default Transformer;

Ни один из методы преобразования, по-видимому, вызываются, поскольку помещение в них операторов console.log(...) не приводит к выводу в консоли.

Здесь настраивается экземпляр store:

import { createStore } from 'redux';
import { persistStore, persistReducer } from 'redux-persist';
import { AsyncStorage } from 'react-native'
import rootReducer from './index';

const persistConfig = {
  key: 'root',
  storage: AsyncStorage,
  whitelist: ['register'],
  blacklist: [],
};

// Middleware: Redux Persist Persisted Reducer
const persistedReducer = persistReducer(persistConfig, rootReducer);
// Redux: Store
const store = createStore(persistedReducer);
// Middleware: Redux Persist Persister
let persistor = persistStore(store);

const getPersistor = () => persistor;
const getStore = () => store;
const getState = () => {
    return store.getState();
};export {
    getStore,
    getState,
    getPersistor
};export default {
    getStore,
    getState,
    getPersistor
}

Всякий раз, когда сохраняется данные получаются после запуска приложения, это выглядит так:

Array [
  Object {
    "days": Array [
      Object {
        ...
      },
      ...
    ],
    ...
  },
]

Вместо того, как это выглядит при сохранении данных:

Array [
  RegistrationWeek {
    "days": Array [
      RegistrationDay {
        ...
      },
      ...
    ],
    ...
  },
]

Я полагаюсь на totalTime() и dateRange() методы из RegistrationWeek объекта в моем пользовательском интерфейсе, но после регидратации он больше не работает, потому что объекты не созданы должным образом. Выполнение этого как части функции рендеринга компонента работает, но недостатком этого является еще большее сочетание шаблонов и манипулирования данными. Циклы также будут повторяться каждый раз при рендеринге компонента, что кажется мне неожиданным влиянием на производительность. Я надеялся, что строгая типизация, трансформатор и конфигурация помогут, но каким-то образом он не вызывается, хотя состояние сохраняется.

Если у кого-то есть какие-либо советы, вещи, которые я пропустил, о том, как поступить с этим, пожалуйста, дайте мне знать!

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...