Reducer querying · Issue #943 · reduxjs/redux (original) (raw)

Is it possible to query reducers, such as for determining whether an async action needs to run or not?

If not, I would like to propose a discussion on the possibility of introducing them. These queries would be their own action type with a payload, except a reducer returns a response instead of the entire state.

They would be polymorphic – not coupled to any particular reducer. This allows more flexible code, rather than having actions having specific knowledge about the structure of the state tree that getState requires (in redux-thunk).

Note this is also distinct from the helper functions that I have seen in examples, where alongside a reducer, other functions are exported to extract data from its state. These are coupled to a particular reducer.

// Action Creator
import { QUERY_TYPE } from 'redux';
const QUERY_WANTS_TO_LOAD_REDDIT = 'QUERY_WANTS_TO_LOAD_REDDIT';

export function fetchPostsIfNeeded(reddit) {
  return (dispatch, getState, query) {
    if (query({ type: QUERY_TYPE, query: QUERY_WANTS_TO_LOAD_REDDIT, reddit }).some(Boolean)) {
      fetchPosts(reddit);
    }
  };
}

// Reducer

function posts(state = { items: [], didInvalidate: true }, action) {
  if (action.type === QUERY_TYPE) {
    switch (action.query) {
      case QUERY_WANTS_TO_LOAD_REDDIT:
        return state.didInvalidate;
    }
  }

  switch (action.type) {
    // Normal handling...
  }
}

export function postsByReddit(state, action) {
  if (action.type === QUERY_TYPE) {
    switch (action.query) {
      case QUERY_WANTS_TO_LOAD_REDDIT:
        return posts(state[action.reddit], action);
    }
  }

  switch (action.type) {
    // Normal handling...
  }
}

I have implemented a system like this in my Redux additions library Flambeau (see https://github.com/BurntCaramel/flambeau/blob/master/docs/reducers.md#introspection), but it would be great to have similar functionality in Redux.

Even just the bare minimum of sending arbitrary messages to reducers without affecting state, and then the rest could be built on top as a plugin?