Redux:可重用的动作

时间:2016-10-10 18:38:18

标签: redux

我有一个使用redux thunk的动作,看起来像这样:

export function fetchData(query) {
  return dispatch => {
    return fetch(`http://myapi?query=${query}` ,{mode: 'cors'})
      .then(response => response.json())
      .then(json => { dispatch(someOtherAction(json)) })
    }
  }
}

然后我的someOtherAction实际更新状态:

export function someOtherAction(data) {
    return {
        action: types.SOME_ACTION,
        data
    }
}

但是我希望fetchData动作创建者可以重复使用,以便我的应用的不同部分可以从myapi获取数据,然后根据该部分拥有状态的不同部分。

我想知道重用此操作的最佳方法是什么?是否可以将第二个参数传递给我的fetchData动作创建者,该参数规定了成功获取时调用的动作:

export function fetchData(query, nextAction) {
  return dispatch => {
    return fetch(`http://myapi?query=${query}` ,{mode: 'cors'})
      .then(response => response.json())
      .then(json => { dispatch(nextAction(json)) })
    }
  }
}

或者有没有可以接受的做这种事情的方式?

1 个答案:

答案 0 :(得分:1)

我使用中间件。我已经在那里定义了fetch调用,然后在我的操作中,我将URL发送到fetch以及完成后调度的操作。这将是典型的获取操作:

const POSTS_LOAD = 'myapp/POST_L';
const POST_SUCCESS = 'myapp/POST_S';
const POST_FAIL = 'myapp/POST_F';

export function fetchLatestPosts(page) {
  return {
    actions: [POSTS_LOAD, POST_SUCCESS, POST_FAIL],
    promise: {
      url: '/some/path/to/posts',
      params: { ... },
      headers: { ... },
    },
  };
}

调用该操作时,中间件将在执行获取请求之前自动调度POST_LOAD操作。如果一切顺利,将使用json响应调度POST_SUCCESS操作,如果出现问题,中间件将调度POST_FAIL操作。

中间件中的所有魔力!它与此类似:

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

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

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

      const [REQUEST, SUCCESS, FAILURE] = actions;
      next({ ...rest, type: REQUEST }); // <-- dispatch the LOAD action


      const actionPromise = fetch(promise.url, promise); // <-- Make sure to add the domain

      actionPromise
        .then(response => response.json())
        .then(json => next({ ...rest, json, type: SUCCESS })) // <-- Dispatch the success action
        .catch(error => next({ ...rest, error, type: FAILURE })); // <-- Dispatch the failure action

      return actionPromise;
    };
  };
}

这样我就可以在一个地方完成所有请求,并且可以在请求完成后定义要运行的操作。

<强> ------------ ---------------- EDIT

要获取reducer上的数据,您需要使用在原始操作创建者上定义的操作名称。以下示例说明如何处理来自中间件的POST_SUCCESS操作,以从posts响应中获取json数据。

export function reducer(state = {}, action) {
  switch(action.type) {
    case POST_SUCCESS:  // <-- Action name
      return {
        ...state,
        posts: action.json.posts, // <-- Getting the data from the action
      }
    default:
      return state;
  }
}

我希望这有帮助!