监听Redux动作

5
我想要创建一个可重用的redux表格模块,其中将存储和更新页码、显示的总页数等信息,我可以在所有页面之间共享该模块。

然而,我需要更新操作触发一个refreshdata动作,该动作将命中不同的终端点,具体取决于页面。

因此,也许可以像页面特定的监听'RefreshData'动作一样,然后触发另一个动作。怎么实现最好呢?我目前使用redux-thunk作为我的中间件,但一直在寻找redux-saga。

最佳实现方法是什么?

**澄清一下**

我在多个页面/项目上都有表格,我想最小化代码重复。我的想法是可能制作一个可放置的redux模块(操作+ reducer),然后仅单独指定REFRESH_DATA操作的处理程序,这样我就不需要在此文件中放置switches。我认为使用redux-saga我可以听取REFRESH_DATA操作,并根据当前页面进行切换?或者有更好的建议。

export const ITEMS_PER_PAGE_UPDATED = 'ITEMS_PER_PAGE_UPDATED'
export const CURRENT_PAGE_UPDATED = 'CURRENT_PAGE_UPDATED'
export const REFRESH_DATA = 'REFRESHDATA'
export const DATA_REFRESHED = 'REFRESHDATA'

export function currentPageUpdated(value) {
    return function (dispatch) {
        dispatch({
            type: CURRENT_PAGE_UPDATED,
            value
        })
        dispatch({type:REFRESH_DATA})
    }
}

export function itemsPerPageUpdated(value) {
    return function (dispatch) {
        dispatch({
            type: ITEMS_PER_PAGE_UPDATED,
            value
        })
        dispatch({type:REFRESH_DATA})
    }
}

function reducer(state={ pageNumber:1, pageSize:10, totalItems:0, totalPages:1, sortColumn:null, sortAscending:true }, action) {
    switch(action.type) {
        case ITEMS_PER_PAGE_UPDATED:
            return Object.assign({}, state, {pageSize: action.value, pageNumber:1})
        case CURRENT_PAGE_UPDATED:
            return Object.assign({}, state, {pageNumber: action.value})
        case DATA_REFRESHED:
            return Object.assign({}, state, {totalPages: action.values.totalPages, totalItems:action.values.totalItems})
        default:
            return state
    }
}

export default reducer

你的问题对我来说有点不清楚。你能给一个更加技术性或结构化的例子吗? - Taner Topal
@TanerTopal 我添加了更多信息。 - Tom
我需要添加更多的代码来进行排序等操作。 - Tom
请查看 https://github.com/slorber/redux-dispatch-subscribe 获取简单的解决方案。 - Sebastien Lorber
1个回答

2
如果我理解正确的话,REFRESH_DATA 动作主要是副作用,也就是说该动作只有在另一个动作的结果下才会被触发。如果是这种情况,那么我认为 Redux Saga 是一个不错的选择,因为它可以在后台“监听”动作并触发其他动作。但是,您可能可以通过自定义 中间件 来实现相似的功能。

使用自定义中间件,您可以在动作传递到 reducers 之前拦截它们。如果您将有一堆与更新表格和刷新数据相关的动作,那么创建一个通用的动作形状来处理所有这些类型的动作可能是有意义的,以便您的中间件可以监听并触发特殊的副作用动作。

一个简单的实现可能如下所示:

middleware/table.js

import fetchData from '../somewhere';
import { DATA_REFRESHED } from '../actions';

// Make a unique identifier that you're actions can send so you're
// middleware can intercept it
export const UPDATE_TABLE = Symbol('UPDATE_TABLE');

export default store => next => action => {
  const tableUpdate = action[UPDATE_TABLE];

  // If the action doesn't have the symbol identifier, just move on
  if (typeof tableUpdate === 'undefined') {
    return next(action);
  }

  // At this point, you know that the action that's been dispatched 
  // is one that involves updating the table, so you can do a fetch
  // for data

  // Get whatever data you need to fetch 
  const { id, type, data } = tableUpdate;

  // Dispatch the actual type of action to the store
  next({ type, data });

  // Go and fetch the data as a side-effect
  return fetchData(id)
    .then(response => next({ type: DATA_REFRESHED, data: response }));
}

actions.js

import { UPDATE_TABLE } from '../middleware/table.js';

// An action creator to dispatch the special table update action
// This is a simple example, but you'd probably want to be consistent
// about how the table update actions are shaped.  The middleware 
// should be able to pick out all of the data it needs to fetch data
// from whatever is sent with the action
function updateTable(action) {
    return {
        [UPDATE_TABLE]: action
    };
}

export function currentPageUpdated(value) {
    return updateTable({
        type: CURRENT_PAGE_UPDATE,
        value
    });
}

我从现实世界的例子中学到了很多,其中包括:https://github.com/rackt/redux/blob/master/examples/real-world/middleware/api.js

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接