当状态树的两个分支具有相同的选择器名称时,如何管理redux选择器

How to manage redux selector when two branches of state tree have same selector name?

本文关键字:选择器 何管理 redux 管理 状态 两个 分支      更新时间:2023-09-26

例如,假设我们有一个称为game的切片状态。在game下我们有两个实体,enemiesitems。每个实体都有x坐标来记录它的位置。状态树如下所示:

{
  game: {
    enemies: {
      allEnemies: [
        {
          id: 1,
          x: 100,
        },
        {
          id: 3,  
          x: 300,
        }
      ],
      allEnemiesById: [1, 3],
    },
    items: {
      allItems: [
        {
          id: 2,
          x: 200,
        },
        {
          id: 7,
          x: 500,
        }
      ],
      allItemsById: [2, 7],
    }
  }
}

当然enemy实体和item实体将有其他不同的属性。也有其他的逻辑在game减速器,所以我不能简单地删除它。

现在,在game减速器中,我们有两个选择器分别获得可见的敌人和道具。它们委托enemiesitems中的选择器功能,因为我不想让game知道enemiesitems的状态树细节:

reducers/game.js

import { enemies, selector1 } from './enemies.js';
import { items, selector2 } from './items.js';
const getVisibleEnemies = (state) => selector1(state.enemies)
const getVisibleItems = (state) => selector2(state.items)

但现在的问题是:selector1selector2的名称应该是什么?我想了一些解决方案,但我不太满意:

(1) getVisibleEntities:但game不能有两个相同的函数名;

(2) getVisibleXXX:但这与game中的选择器名称相同。

(3)直接在客户端代码中调用enemiesitems的选择器,例如(mapStateToProps中的getVisibleEnemies(state.game.enemies)):但是现在调用者必须知道状态树的深层形状,一旦状态树发生变化,要全部更改将是痛苦的。

(4)在reducer函数中绑定选择器,例如:

reducers/enemies.js导出const getVisibleEntities(state) => {//为敌人实现getVisibleEntities}

export const enemies = (state = initialState, action) {
  // main reducer of enemies
}
enemies.getVisibleEntities = getVisibleEntities

reducers/items.js导出const getVisibleEntities(state) => {//getVisibleEntities的实现}

export const items = (state = initialState, action) {
  // main reducer of items
}
items.getVisibleEntities = getVisibleEntities

reducers/game.js

export const getVisibleEnemies = (state) => enemies.getVisibleEntities(state.enemies)
export const getVisibleItems = (state) => items.getVisibleEntities(state.enemies)

但是我不确定是否将选择器设置为状态减速器上的属性是个好主意。

(5)给它一个稍微不同的名字,例如game.js中的getVisibleEnemiesenemies.js中的getVisibleEnemiesImpl:这很好,但我想知道应该有更好的方法来处理这个

那么你会怎么做呢?

我认为你应该选择选项(3),但是:

  • 选择器应该是整个Redux存储状态的函数
  • 这样你的容器(智能组件)就不需要知道你的状态树的深层形状