Figuring Out Redux Best Practices (Part 2)
living with getState()
Part one is in the books. I have put it behind me along with my frustrations about where to put my logic in a Redux application. The simple fact is that one must accept some imperative responsibility even when using declarative, functional libraries. After all, programmers would be out of work if libraries and frameworks did everything for us.
Conditional Dispatches
So yeah, eventually you just need to make the call on whether to split your dispatch into 3 different functions or bundle them as one. This seems difficult at first but it actually follows a simple rubric for me.
- Do the actions being dispatched do completely unrelated things? Then don’t put them together.
- Do they rely on one another in a time-sensitive way? Well then yeah you kind of have to use thunks to dispatch them and run your conditional statements.
If you’re like me and you’re reading this then I’ll go ahead and answer the question in your mind — Yes I do hate myself for this.
const checkForBlackJack = (playerCards) => { /*logic to ...well come on I write descriptive function names for a reason ;)*/
}const dealCard = (card) => (dispatch, getState) => {
dispatch({type: 'DEAL_CARD', card, meta: {delay: 500}}).then(() => { let { cards } = getState().player
dispatch(checkForBlackJack(cards))
})
}
You can write it as pretty as you please with all sorts of arrows but at the end of the day it’s still strange looking. Some middleware is catching the meta property and setting the dispatch to be delayed AND to return to me on promise completion. Player cards have changed since the beginning of this thunk, so I must call getState() to have accurate information for the checkForBlackJack() dispatch.
Why do I hate this?
Well I did for a while. I hear a lot these days about the importance of pure functions and this certainly isn’t one — The same input can result in a different return value since it relies on outside state. But at the end of the day there is a reason why getState() is a built in method for Redux thunks. You don’t want pieces of state to rely on other pieces of state when possible but sometimes they do.
Joe’s personal guidelines
I’m reading about redux literally every day so these are subject to (the guarantee of) change but I have a few principles when building in Redux.
- Avoid thunks whenever possible. Split up your ACs.
- If you feel like your ACs file(s) are messy, you’re probably underutilizing your containers and reducers.
- ^If any of those things are messy, it’s probably because you’re underutilizing one or both of the other ones.
- If your code is sound, works well, but seems just a tiny bit messy to you and only you….well then you’re a programmer.