使用包含承诺的 createselector 反应 redux 容器

React redux container with createselector that contains a promise

我有一个连接到商店的容器,每秒更新一次:

return ({ match, ui }, { matchId }) => ({
    value: match.getIn([matchId, 'masterCurrentTime'], 0), // about every second
    min: ui.get('seekStart'),
    max: ui.get('seekEnd'),
    highlightList: selectHighlights(matchId) // i only want to do this on first render
  });

然而,其中一个属性 (highlightList) 执行以下两项操作之一:

1) return 来自 sessionStorage 的值

2) 下载一个文件,将其保存到 sessionStorage,然后 returns 它

当然我不想每秒钟都这样做,只有第一次。

我创建了一个这样的选择器

const selectHighlights = createSelector(
    matchId => matchId,
    matchId => {
      if (matchId !== null) {
        getTimelineWithFilter(matchId, ['round_start'])
          .then(timeline => {
            console.log(timeline);
            return timeline;
          })
          .catch(error => {
            throw new Error('failed to load highlights', error);
          });
      }

      return null;
    }
  );

但是不行,没有渲染。 但是,如果我做一个替代版本,我将结果存储在一个变量中,然后查询它,事情就可以了。它只运行一次并按我喜欢的方式执行

// highlightList: currentTimeline === undefined ? loadHighlights(matchId) : currentTimeline,

我只是想学习如何以正确的方式做到这一点,有这方面知识的人可以给我一些最佳实践技巧吗?

如何在 React-Redux 应用程序中处理承诺?

假设您有一个 action creator 用于从某些 API 获取数据。您将从您的组件调度操作(加载/点击/其他事件)。

export function loadData(key) {
  return {
    types: [LOAD_DATA, LOAD_DATA_SUCCESS, LOAD_DATA_FAIL]
    promise: () => fetch(...), // API call that returns a promise
    key,
  }
}

现在在创建 store 时创建一个 middleware for promise based operations. Make sure you applyMiddleware

The most common use case for middleware is to support asynchronous actions without much boilerplate code or a dependency on a library like Rx. It does so by letting you dispatch async actions in addition to normal actions.

export default function clientMiddleware() {
  return ({ dispatch, getState }) => next => (action) => {
    if (typeof action === 'function') {
      return action(dispatch, getState);
    }

    const { promise, types, ...rest } = action;

    if (!promise) {
      return next(action);
    }

    const [REQUEST, SUCCESS, FAILURE] = types;

    next({ ...rest, type: REQUEST });

    const actionPromise = promise();
    actionPromise
      .then(result => next({ ...rest, result, type: SUCCESS }))
      .catch(error => next({ ...rest, error, type: FAILURE }));

    return actionPromise;
  };
}

最后这是你的 initialState:

const initialState = {
  isLoading: false,
  isLoaded: false,
  data: {},
  error: null,
};

减速器

case LOAD_DATA:
  return {
    ...state,
    isLoading: true
  };

case LOAD_DATA_SUCCESS:
  return {
    ...state,
    isLoading: false,
    isLoaded: true,
    data: action.result,
  };

case LOAD_DATA_FAIL:
  return {
    ...state,
    isLoading: false,
    isLoaded: false,
    error: action.error
  };