推荐关注
Meteor
JSLint - a JavaScript code quality tool
jsFiddle
D3.js
WebStorm
推荐书目
JavaScript 权威指南第 5 版
Closure: The Definitive Guide
ethusdt
0.01D

如何修改当前的 Redux Store 来应对项目需求更改?

  •  
  •   ethusdt · Dec 7, 2019 · 3764 views
    This topic created in 2370 days ago, the information mentioned may be changed or developed.

    想不出来合适的标题, 可以有偿求解决方案, 这是由于业务新增需求导致不清楚应该如何解决.

    before

    这是之前的页面, 个人中心有「商品订单」和「服务订单」的入口, 可以跳转到不同的 tab (上面的 tab)页. App 是用 RN 写的, 用到了 redux + saga, 其中这俩订单页面的数据统一放到一个 state 中, 页面有分页功能, 从订单列表页面还可以跳转订单详情, 订单的操作有支付,取消订单,确认收货等, 可以在列表与详情中操作, 在详情中操作需要同步到列表, 所以详情页的数据也是取自这个 state. 使用 redux 好处是可以让数据放到内存中, 切换页面不会丢失数据. state 是这样的解构:

    const INIT_STATE = {
      current: TAB[0],
      loading: true,
      allS: {
        page: 1,
        list: []
      },
      allG: {
        page: 1,
        list: []
      },
      unpayS: {
        page: 1,
        list: []
      },
      unpayG: {
        page: 1,
        list: []
      },
      unconfirmS: {
        page: 1,
        list: []
      },
      ...
    

    对应的操作都是通过 saga 来处理:

    function* handleFetch() {}
    function* handleChangeTab() {}
    function* handleRefresh() {}
    function* handleCancelOrder() {}
    function* handlePay() {}
    ...
    

    到这里是没问题的, 功能挺完善, 但是新需求来了, 要增加一个页面, 这个页面是两个订单列表的组合, 通过调用一个接口, 分页获取订单, 按照时间的排序, 保留之前两个列表, 新增的这个页面上面有之前订单列表的入口:

    after

    这里就出现了几个比较棘手的问题, 先说一下我怎么实现的: 新的列表页不用 redux, 请求数据直接渲染列表, 当发生订单操作时候, 清理掉之前的订单列表的 redux 数据(比较偷懒)来解决多列表同步问题. 当跳转产品详情页时候, 产品详情的数据是取自之前列表, 怎么解决没有数据这个问题呢? 添加一个HACKaction, 当跳转详情之前, 先把数据 hack 到之前的列表中. 那么马上就遇到下面的问题, 当在详情里进行订单操作时候, 如何同步到新的列表? 如果是从之前列表跳转详情, 如何同步新的列表与旧的列表?

    看来不使用 redux 来混合 redux 开发是死路一条, 那么我又想到了几种方案, 但都是有问题的:

    方案一: 新的列表页面使用旧列表页面的 redux 数据, 新页面加载时候直接给旧列表发送请求, 一份数据多个列表使用. 这个方案不可行原因是新的列表是按照下单时间排序的, 可能会有「商品」「服务」「商品」这种混合订单, 没法满足需求.

    方案二: 新建一个 state, 这个 state 给新的列表使用, 但会和旧的 state 共用一些 actions, 详情页面的数据取自两个 state, 因为都对应同一订单. 但是这个方案的问题也比较明显, 比如在详情页面选择支付, 会发送一个支付 action, 那么处理这个 action 的应该是哪一个呢?

    暂时没有想到其他的解决方法, 问题比较长, 希望能够看得明白.

    4 replies    2019-12-08 12:35:23 +08:00
    dremy
        1
    dremy  
       Dec 7, 2019 via iPhone
    建议还是不要将这些页面数据存储到全局状态中共用,而是每个页面单独维护自己的数据状态,当然登录信息之类必须共用的除外
    cfy
        2
    cfy  
       Dec 7, 2019
    store 里加一个 flag,传递给订单列表页面;
    如果需要展示新数据,跳转到订单列表页面之前,
    发 api 请求更新 store,设置 flag ;更新 store 订单数据后再更改 flag ;
    订单列表页面通过 store 获取 flag,看业务场景是先展示旧数据,还是等待新数据更新,就可以了。

    数据源不止一个的话,就会给项目维护埋坑。
    ethusdt
        3
    ethusdt  
    OP
       Dec 7, 2019
    @cfy 谢谢 「数据源不止一个的话,就会给项目维护埋坑」真的是这样子的, 但是业务场景不在乎代码. 站在开发者角度, 应该尽可能给后人提供容易维护的代码.
    ethusdt
        4
    ethusdt  
    OP
       Dec 8, 2019
    解决了, 采用的方法是新增一个 redux state: anotherOrderList (起名的艺术).
    它和之前的 reducer 共享一些操作 actions:

    ```
    export function* watchOrderCalcel() {
    yield takeLatest(types.SAGA_ORDER_CANCEL, handleCancel)
    }
    export function* watchOrderReceive() {
    yield takeLatest(types.SAGA_ORDER_RECEIVE, handleReceive)
    }
    export function* watchOrderPay() {
    yield takeLatest(types.SAGA_ORDER_PAY, handlePay)
    }
    export function* watchOrderEvaluation() {
    yield takeLatest(types.SAGA_ORDER_EVALUATION, handleEvaluate)
    }
    ```

    新增俩给 anotherOrderList 使用的:

    ```
    // ANOTHER ORDER LIST
    export function* watchAnotherOrderFetch() {
    yield takeLatest(types.SAGA_ANOTHER_ORDER_LIST_FETCH, handleAnotherFetch)
    }
    export function* watchAnotherOrderRefresh() {
    yield takeLatest(types.SAGA_ANOTHER_ORDER_LIST_REFRESH, handleAnotherRefresh)
    }
    ```

    在订单详情里要处理下, 取两个 list 的数据:
    ```
    const mapState = (state, ownProps) => {
    const { navigation } = ownProps
    const orderId = navigation.getParam('orderId')
    if (orderId) {
    const { orderList, anotherOrderList } = state
    const l1 = orderList[orderList.current.value].list
    const l2 = anotherOrderList.list
    const cond = item => item.orderId === orderId
    const data = l1.find(cond) || l2.find(cond)
    return {
    orderId,
    orderStatus: data.orderStatus
    }
    }
    return null
    }
    ```

    共享 actions 的方法里要做对新的 list 兼容.
    About   ·   Help   ·   Advertise   ·   Blog   ·   API   ·   FAQ   ·   Solana   ·   5725 Online   Highest 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 41ms · UTC 06:17 · PVG 14:17 · LAX 23:17 · JFK 02:17
    ♥ Do have faith in what you're doing.