Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/asp.net/31.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
React native 反应redux异步数据同步,然后重新渲染视图_React Native_React Redux_Redux Thunk - Fatal编程技术网

React native 反应redux异步数据同步,然后重新渲染视图

React native 反应redux异步数据同步,然后重新渲染视图,react-native,react-redux,redux-thunk,React Native,React Redux,Redux Thunk,我为不同的内容类型(如页面、活动和场地)设置了许多操作和简化程序。这些操作和还原程序获取另一个名为sync的操作保存到AsyncStorage的数据,并将其放入存储区 Sync对Contentful执行异步调用并检索任何新的/更新的/删除的条目,然后将其保存到AsyncStorage 确保在异步调用完成后正确重新呈现视图的最佳方法是什么 syncReducer是否应该将数据合并到通常由pagesReducer、venuesReducer等拉出的存储中,或者在syncReducer完成后是否应该发

我为不同的内容类型(如页面、活动和场地)设置了许多操作和简化程序。这些操作和还原程序获取另一个名为sync的操作保存到
AsyncStorage
的数据,并将其放入存储区

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

确保在异步调用完成后正确重新呈现视图的最佳方法是什么

syncReducer
是否应该将数据合并到通常由
pagesReducer
venuesReducer
等拉出的存储中,或者在
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
  };
}
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
  };
}
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;
操作/getPages.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
  };
}
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
  };
}
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;
减速机/pagesReducer.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
  };
}
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
  };
}
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;

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

对于要重新呈现的每个组件(基于存储中通过我们刚才调度和减少的操作更新的数据),如果您有
connect(MapStateTops,mapDispatchToProps)
,并且已将存储的这些部分包含在MSTP中,则将更新这些将重新呈现组件的道具

如果有必要,您甚至可以通过创建另一个操作来更明确地说明数据的解析,在该操作中,您可以调度并将获取的当前状态减少到存储的某个部分


因此,当您进行调用时,您可以调度“FETCH_IN_PROGRESS”,然后是“FETCH_ERROR”或“FETCH_SUCCESS”,如果这是映射到组件中的MapStateTrops,您可以选择在shouldComponentUpdate()中对其进行求值,并根据它在进程中的位置,根据是否要重新提交,可以返回true或false。您还可以强制在componentWillReceiveProps中进行渲染。我将从依赖道具开始,在必要时更改和添加道具。

您应该使用Redux Persist对于这类东西,它支持异步存储和一系列其他选项

操作和缩减器的设计应该只是为了更新Redux存储。任何其他操作都称为副作用,应该在中间件或存储增强程序中进行管理

我强烈建议不要使用Redux Thunk,因为它太强大了,不适用于少数有用的东西,而且很容易创建无法维护的反模式代码,因为它模糊了操作和中间件代码之间的界限


如果您认为需要使用Redux Thunk,请首先查看他们的中间件是否已经满足您的需要,如果还没有了解Redux传奇

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

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

  };
}

您可以添加一些真实代码或伪代码来说明数据流是什么吗?您需要使组件响应属性更改。在数据可用之前,数据同步不应更改道具。这意味着您应该在一个异步redux操作中完成这一切(我更喜欢使用sagas)。这样,一旦完成所有异步工作,它只需使用就绪数据更新存储一次。所以你的组件真的可以是“哑的”/“纯的”,只是基于道具进行渲染。@markerikson如果有帮助的话,我已经用一些精简的代码更新了我的问题。