重新选择和递归选择器

时间:2017-06-26 13:34:51

标签: javascript redux reselect

我有一个带有项目树(规范化)的redux状态,如:

state = {
  items: [
    { id: 1, parent: null, children: [2, 3] },
    { id: 2, parent: 1, children: [4] },
    { id: 3, parent: 1, children: [], value: 10 },
    { id: 4, parent: 2, children: [], value: 20 }
  ]
}

我想获得第1项的减值总和(此处= 10 + 20 = 30),我想为此创建一个重选选择器。

但是,我如何定义递归选择器?

感谢您的帮助。 ; - )

弗雷德里克

2 个答案:

答案 0 :(得分:1)

我将更新@Vanojx1代码以提出2个解决方案:

(免责声明:我是重新选择的作者,但这是一个典型的用例)

基本代码

let state = {
    items: [
        { id: 1, parent: null, children: [2, 3] },
        { id: 2, parent: 1, children: [4] },
        { id: 3, parent: 1, children: [], value: 10 },
        { id: 4, parent: 2, children: [], value: 20 }
    ]
};

function getSum(items, id) {
  let item = items.find(item => item.id == id);
  return item.hasOwnProperty('value') ? item.value : item.children.reduce((current, next) => {
    return current + getSum(items, next);
  }, 0);
}

解决方案1 ​​ - 仅重新选择

import { createSelector } from 'reselect';

const getSumSelector = createSelector(
  (state) => state.items,
  (state, id) => id,
  (items, id) => getSum(items, id)
);

getSumSelector(state, 1);
// Loses memoization with sequentials calls with same items but different id's

解决方案2 - 重新选择+重新选择

import createCachedSelector from 're-reselect';

const getSumSelector = createCachedSelector(
    state => state.items,
    (state, id) => id,
    (items, id) => getSum(items, id)
)(
    // Cache selector by id
    (state, id) => id
);

getSumSelector(state, 1);

答案 1 :(得分:0)

试试这个:

let state = {
    items: [
        { id: 1, parent: null, children: [2, 3] },
        { id: 2, parent: 1, children: [4] },
        { id: 3, parent: 1, children: [], value: 10 },
        { id: 4, parent: 2, children: [], value: 20 }
    ]
}

function getSum(state, id) {
  let item = state.items.find(item => item.id == id);
  return item.hasOwnProperty('value') ? item.value : item.children.reduce((current, next) => {
    return current + getSum(state, next);
  }, 0);
}

let sum = getSum(state, 1);

console.log(sum);