想不出来合适的标题, 可以有偿求解决方案, 这是由于业务新增需求导致不清楚应该如何解决.
这是之前的页面, 个人中心有「商品订单」和「服务订单」的入口, 可以跳转到不同的 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() {}
...
到这里是没问题的, 功能挺完善, 但是新需求来了, 要增加一个页面, 这个页面是两个订单列表的组合, 通过调用一个接口, 分页获取订单, 按照时间的排序, 保留之前两个列表, 新增的这个页面上面有之前订单列表的入口:
这里就出现了几个比较棘手的问题, 先说一下我怎么实现的: 新的列表页不用 redux, 请求数据直接渲染列表, 当发生订单操作时候, 清理掉之前的订单列表的 redux 数据(比较偷懒)来解决多列表同步问题. 当跳转产品详情页时候, 产品详情的数据是取自之前列表, 怎么解决没有数据这个问题呢? 添加一个HACK
action, 当跳转详情之前, 先把数据 hack 到之前的列表中. 那么马上就遇到下面的问题, 当在详情里进行订单操作时候, 如何同步到新的列表? 如果是从之前列表跳转详情, 如何同步新的列表与旧的列表?
看来不使用 redux 来混合 redux 开发是死路一条, 那么我又想到了几种方案, 但都是有问题的:
方案一: 新的列表页面使用旧列表页面的 redux 数据, 新页面加载时候直接给旧列表发送请求, 一份数据多个列表使用. 这个方案不可行原因是新的列表是按照下单时间排序的, 可能会有「商品」「服务」「商品」这种混合订单, 没法满足需求.
方案二: 新建一个 state, 这个 state 给新的列表使用, 但会和旧的 state 共用一些 actions, 详情页面的数据取自两个 state, 因为都对应同一订单. 但是这个方案的问题也比较明显, 比如在详情页面选择支付, 会发送一个支付 action, 那么处理这个 action 的应该是哪一个呢?
暂时没有想到其他的解决方法, 问题比较长, 希望能够看得明白.
1
dremy 2019-12-07 17:11:07 +08:00 via iPhone
建议还是不要将这些页面数据存储到全局状态中共用,而是每个页面单独维护自己的数据状态,当然登录信息之类必须共用的除外
|
2
cfy 2019-12-07 17:32:55 +08:00
store 里加一个 flag,传递给订单列表页面;
如果需要展示新数据,跳转到订单列表页面之前, 发 api 请求更新 store,设置 flag ;更新 store 订单数据后再更改 flag ; 订单列表页面通过 store 获取 flag,看业务场景是先展示旧数据,还是等待新数据更新,就可以了。 数据源不止一个的话,就会给项目维护埋坑。 |
3
FaiChou OP @cfy 谢谢 「数据源不止一个的话,就会给项目维护埋坑」真的是这样子的, 但是业务场景不在乎代码. 站在开发者角度, 应该尽可能给后人提供容易维护的代码.
|
4
FaiChou OP 解决了, 采用的方法是新增一个 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 兼容. |