user3272018
user3272018

Reputation: 2429

Using reselect-selectors in a reducer

Let's say there is a tree in the state of my react-redux app and tree belongs to myReducer. In many cases I need this tree flattened, so I've got a selector:

const getTree = state => state.myReducer.tree;

export const getFlatNodes = createSelector(
    [getTree],
    (tree) => flattenTree(tree)
);

And now I need to access the flattened tree in an action

import { getFlatNodes } from 'path/to/selectors';

function myReducer(state = defaultState, action) {
    switch (action.type) {
       case SOME_ACTION:
           const flattenedTree = getFlatNodes(state);
           return {
               ...state,
               smth: getSmthFromFlattenedTree(flattenedTree)
           };
    }
}

This code will not work as expected since state in the reducer is just a slice of the app state. A simple workaround I came up with is to wrap state to make the passed parameter compatible:

import { getFlatNodes as _getFlatNodes } from 'path/to/selectors';
const getFlatNodes = myReducer => _getFlatNodes({ myReducer });

The code works, although it looks quite hacky and I'm not sure if it won't cause any issues.

Does anybody have any idea why and how it can be done better or my approach is good enough already?

Upvotes: 1

Views: 1418

Answers (1)

Safi Nettah
Safi Nettah

Reputation: 1170

Maybe if you make that in your action

const someAction = () => (dispatch, getState) => ({
  type: 'SOME_ACTION',
  payload: getFlatNodes(getState())
  // payload: getSmthFromFlattenedTree(getFlatNodes(getState()))
});

then in your reducer

function myReducer(state = defaultState, action) {
    switch (action.type) {
       case SOME_ACTION:
           return {
               ...state,
               smth: getSmthFromFlattenedTree(action.payload)
           };
    }
}

Upvotes: 1

Related Questions