Tiddo
Tiddo

Reputation: 6544

Proper patterns to react to redux store changes

Usually in Redux we listen for actions in middleware/reducers to perform operations. However, at times we're not interested in actions, but in store changes themselves. This is especially relevant when multiple actions can lead to the same store changes. How can I do so in an idiomatic way?

Consider for example a section of the store in which we have the current path of a SPA:

const store = {
    url : '/'
};

Changing the url can happen in one of 3 ways: popState, pushState or replaceState. A logical implementation would be to have separate actions for the 3, such that we can handle them separately in middleware. E.g.:

//actions
function popState(url) {
  return { type : 'POP_STATE', url };
}
function pushState(url) { 
  return { type : 'PUSH_STATE', url };
}
function replaceState(url) {
  return { type : 'REPLACE_STATE', url };
}

// middleware
store => next => action => {
  switch(action.type) {
    case 'PUSH_STATE' : 
      history.pushState(null, null, action.url);
      break;
    case 'REPLACE_STATE' :
      history.replaceState(null, null, action.url);
      break;
  }
  return next(action);
}

// reducer
function (state, action) {
  switch(action.type) {
    case 'PUSH_STATE':
    case 'REPLACE_STATE':
    case 'POP_STATE':
      state.url = action.url; // (ignoring immutability to keep the example simple)
      break;
  }
  return state;
}

Now I want to respond to url changes, but I don't care how the url changed. I see a few options, but I'm not sure if either of them follows the redux paradigms properly:

Do any of these solutions fall within the paradigms of redux? Did I miss any?


Meta note: I'm aware that this question could be interpreted as "primarily opinion based", but I disagree: I'm not looking for the best or most elegant solution, I'm trying to assert which solution(s) fit(s) the redux paradigm, and I believe there are definite, objective answers to that.

Upvotes: 0

Views: 215

Answers (2)

zloctb
zloctb

Reputation: 11177

Good pattern middleware :

const logMiddleware => ({ getState, dispatch }) => next => action => {
     console.log("Before reducers have run");
     console.log(getState());
     next(action);
     console.log("After the reducers have run");
     console.log(getState());
     };

Upvotes: 0

markerikson
markerikson

Reputation: 67459

Using store.subscribe() is a valid option if you need it. There's many existing libraries to help watch for changes in the store state if you need to do so outside of connected React components. Given that you're doing routing-related behavior, you may also be interested in some of the existing Redux-based routing libraries as well.

Upvotes: 1

Related Questions