React redux异步数据同步然后重新渲染视图

时间:2017-11-29 14:05:45

标签: react-native react-redux redux-thunk

我为不同的内容类型设置了许多操作和缩减器,例如页面,活动和场地。这些操作和缩减器通过另一个名为sync的操作获取已保存到AsyncStorage的数据,并将其放入存储中。

Sync对Contentful执行异步调用并检索任何新的/更新/删除的条目,然后将其保存到AsyncStorage

在异步调用完成后,确保正确查看视图的最佳方法是什么?

syncReducer应该将数据合并到通常由pagesReducervenuesReducer等提取的商店中,还是应该在syncReducer完成后发生某种事件?

数据被异步拉入以便离线查看并保持快速,所以我真的不想在渲染之前等待同步。

data / sync.js

import { AsyncStorage } from 'react-native';

import database from './database';

const cache = {
  getByType: async (query) => {
    return new Promise(async(resolve, reject) => {
      // Get results from AsyncStorage
      resolve(results);
    });
  },

  sync: async () => {
    return new Promise(async(resolve, reject) => {
      database
        .sync(options)
        .then(async results => {
          // Save results to AsyncStorage
          resolve(results);
        });
    });
  }
};

export default cache;

操作/ sync.js

import actionTypes from '../constants/actionTypes';
import cache from '../data/cache';

export function sync() {
  return dispatch => {
    dispatch(syncRequestedAction());

    return cache
      .sync()
      .then(() => {
        dispatch(syncFulfilledAction());
      })
      .catch(error => {
        console.log(error);
        dispatch(syncRejectedAction());
      });

  };
}


function syncRequestedAction() {
  return {
    type: actionTypes.SyncRequested
  };
}

function syncRejectedAction() {
  return {
    type: actionTypes.SyncRejected
  };
}

function syncFulfilledAction(data) {
  return {
    type: actionTypes.SyncFulfilled,
    data
  };
}

操作/ getPages.js

import actionTypes from '../constants/actionTypes';
import cache from '../data/cache';

export function getPages() {
  return dispatch => {
    dispatch(getPagesRequestedAction());

    return cache
      .getByType('page')
      .then(results => {
        dispatch(getPagesFulfilledAction(results));
      })
      .catch(error => {
        console.log(error);
        dispatch(getPagesRejectedAction());
      });

  };
}


function getPagesRequestedAction() {
  return {
    type: actionTypes.GetPagesRequested
  };
}

function getPagesRejectedAction() {
  return {
    type: actionTypes.GetPagesRejected
  };
}

function getPagesFulfilledAction(settings) {
  return {
    type: actionTypes.GetPagesFulfilled,
    pages
  };
}

减速器/ pagesReducer.js

import { merge } from 'lodash';

import actionTypes from '../constants/actionTypes';

const pagesReducer = (state = {}, action) => {
  switch (action.type) {
    case actionTypes.GetPagesRequested: {
      return merge({}, state, { loading: true });
    }
    case actionTypes.GetPagesRejected: {
      return merge({}, state, { error: 'Error getting pages', loading: false });
    }
    case actionTypes.GetPagesFulfilled: {
      const merged =  merge({}, state, { error: false, loading: false });
      return { ...merged, data: action.pages };
    }
    default:
      return state;
  }
};

export default pagesReducer;

3 个答案:

答案 0 :(得分:0)

最后,我能够通过将其他操作导入到我的同步操作中来解决此问题,并根据需要更新的数据进行调度。

import { getEvents } from './getEvents';
import { getPages } from './getPages';
import { getVenues } from './getVenues';

export function sync() {
  return dispatch => {
    dispatch(syncRequestedAction());

    return cache
      .sync()
      .then(results => {
        dispatch(syncFulfilledAction());

        if (results.includes('event')) {
          dispatch(getEvents());
        }

        if (results.includes('page')) {
          dispatch(getPages());
        }

        if (results.includes('venue')) {
          dispatch(getSettings());
        }

      })
      .catch(error => {
        console.log(error);
        dispatch(syncRejectedAction());
      });

  };
}

答案 1 :(得分:-1)

您的同步操作应该是一个thunk函数(redux中间件),它调用Contentful,解析promise,并包含数据或错误。然后,您可以调度另一个操作或操作以将数据减少到存储中。

在您要重新呈现的每个组件上(基于通过我们刚刚调度和减少的操作在商店中更新的数据),如果您有connect(mapStateToProps, mapDispatchToProps)并且已包含商店的这些部分MSTP,这些道具将被更新,这将重新渲染组件。

如果有必要,您甚至可以通过创建另一个操作来更明确地解决数据,您可以将调度的当前状态分派并减少到商店的某个部分。

因此,当您进行调用时,您可以调度'FETCH_IN_PROGRESS',然后调用'FETCH_ERROR'或'FETCH_SUCCESS',如果这是mapStateToProps到您的组件,您可以选择在shouldComponentUpdate()中根据其中的位置进行评估它是一个过程,你可以根据你想要重新渲染的方式返回true或false。您还可以在componentWillReceiveProps中强制渲染。我开始只依靠道具改变并在必要时添加它。

答案 2 :(得分:-1)

你应该使用 Redux Persist 来做这种事情,它支持AsyncStorage和一系列其他选项。

https://github.com/rt2zz/redux-persist

操作和减少器应该只是为了更新Redux商店而设计的。任何其他操作都称为副作用,应在中间件或Store Enhancer中进行管理。

我强烈建议不要使用Redux-Thunk,这对于它有用的一些东西来说太强大了,并且很容易创建不可维护的反模式代码,因为它模糊了操作和中间件代码之间的界限。

如果您认为需要首先使用Redux-Thunk,请查看它们是否已经是一个能够满足您需求的中间件,如果不了解Redux-Sagas。