Your cart is currently empty!
The React-Redux Flow: A State of Dystopia
BACKGROUND: As I work through the final project of Flatiron’s curriculum, I initially found the Redux implementation to be overkill. Having completed my app using React along with State and Props, it was frustrating to attempt a Redux refactor as I found myself mostly adding code (as opposed to taking it away). Ultimately, I wiped out the entire front end of my project, to symbolically “burn the ships”, but also to start with a clean-ish slate.
Thanks to great insights and advice from a fellow Flatiron Student, I now think I’ve “Seen The Light” in the value of Redux. Reflecting on what I learned, and why it took me two weeks to wrap my head around it conceptually… I suspect part of the difficulty was due to the amount of abstraction, coding conventions (that while helpful in the long run) obfuscate the conceptual flow, and lastly technical vocabulary that seems to make sense mostly after you already understand it.
With that mind, I’d like to present a dystopian analogy that I hope is not only memorable but illustrative. If you’re entirely new to React and Redux, this might help you discover a mental model to “map” code to. If you’ve been working with React, have some understanding of state and props, but difficulty internalizing the React-Redux flow, this post is for you.
THE ANALOGY:
Suppose you’re living in some dystopia. Something of a cross between Orwell’s “1984”, Huxley’s “Brave New World”, with a bit of Vonnegut’s “Harrison Bergeron”. You are a coder that’s being given a chance to escape the gulag and pull the levers of society by helping Big Brother develop some new spy machinery.
Consider Provider
as a stand in for “Big Brother”. It wraps your entire app
or CityState
or whatever is that outermost container of your application. Whatever is within the iron grip of Big Brother “The Provider” abides by the rules set in The Store
. Keep in mind, that not all of your app must be oppressed by The Provider. Select elites might be in an entirely different container, one that is exempt from the rules of The Provider and its Store.
“The Store” is where all the Reducers live. One might think of The Store as the The Ministry of Justice from 1984. The Reducers might be the spies, snitches, and “eyes” that make it possible for The Provider (Big Brother) to enforce ‘justice’. Sometimes The Reducers might be organized by category (separation of concerns), or they might be a bunch of free agents that are brought together only by combineReducers
… but they always have one eye on the state
of the situation, and another on whatever action
is taking place.
Imagine that within each Reducer’s department there’s a Desk Clerk that serves as a switch
, checking to see what action.type
(infraction) has been committed, and then passes that complaint off to the corresponding case
worker. Once it’s handed off to the case worker, a “payload
” is returned.
Keep in mind that payload
is essentially jargon. They could just as easily have said “punishment” or “whatever comes back when the action.type is met”, but “payload” sounds better and gives department “Lifers” something to chuckle about when meting out punishments to their victims.
Something like “it’s a case
of ‘the action’ SHARED_FAKE_NEWS
” prompting the dispatch
of “payload”: HARD LABOR IN THE COAL MINES!
The punishment (or payload) is created by The Action Creators. The Action Creators might be likened to a task force that determine what types
of crimes, infractions, actions
are worthy of punishment, and what those punishments, payloads
(returns) should be.
The Action Creators are never the ones that execute the actions they’ve come up with. Or at least they prefer not to be. It is possible to connect
some aspect of a component
with a function that must be executed by the action creator… although, typically, it’s best practice for the “Action Creators” not to get their hands dirty. For that, there is The Executioner known as the Dispatcher. The dispatcher is seemingly all places at all times; the dispatcher comes built-in with Redux and is literally on the same level as the State. All one need do is invoke the name dispatch
and out of the dark the dispatcher will crawl to dish out some payload
.
So, you might be wondering, what’s with all this delegation? In a dystopia, the evil-doers like to split up their atrocities so as not to wear down any single ‘organ’ of the machine. If the Reducers not only spied on the victims but committed the punishment (as opposed to delegate it), their consciences might revolt and errors
would be made. A rule
or key point of the redux flow is to remember: you don’t mutate the state. The state mutates you. A corollary to this is that individual aspects of a component have no power to alter the state of things, except by going to/through the reducers, and ONLY if the thing they want to do has been pre-approved by some Action Creator. In other words, if there is no pre-existing type
as returned/defined by dispatch
, it might as well not exist. (If there is no “law” action type
against it, then no punishment payload
exists)
BACK TO REALITY:
Hopefully, the analogy above should provide some picture of how things might work behind the scenes. Or at least some picture of how a dystopia might operate faithfully in the context of the react-redux flow. Beyond that configuration, the rubber always hits the road inside of the components
or containers
. Keep in my that if you want to manage state locally (or without Redux), you’ll need to use classes, or Hooks. It’s also worth mentioning that even in a Redux app, you’ll likely want to use Local State to manage simple forms (in tandem with Lifecycle Methods) to cut down on the need for code that is only needed within some local/confined scope.
The connect method is most frequently written as export default connect( mapStateToProps, mapDispatchToProps )(YourContainerOrComponent);
The above code example must ALWAYS be the last bit of code. It can’t come before your Class with its render
and return methods because of the way JavaScript processes your code.
On the flip side, while it is convention to write out the code for mapStateToProps
and mapDispatchToProps
outside of the class and immediately before the connect method at the bottom of the file… you CAN actually place them above the Class, under your import statements.
For me (and this is my opinion only), but as you The Learner are trying to bring yourself up to speed with how React-Redux integrate, I think it’s easier mentally to put the code for mapStateToProps
and mapDispatchToProps
above the Class. Why? Because the code you define in mapStateToProps
with the state
you want to reference (along with the appropriate reducer to return that state) are practically stand-ins for the the type of code you would’ve previously written at the top of the file to set state.
As for the code you write inside of mapDispatchToProps
you have a list of the functions (along with local names — typically the same as their const
names from actions
) which you intend to use locally. These are typically arrow functions which, after the arrow, invoke dispatch
along with the type
of action
for dispatch to look for in your actions. If you were writing this all out manually (using only React and not Redux), then these type of functions would be written using state, props, and import statements. With that in mind, it feels more “natural” to include it at the top of the file.
Having run through my app the first time around using state and props, plus having to cross reference an action file, a reducer file, and the component making use of them both (and attempting to make sure I didn’t screw anything up in some index along the way), I feel I’d have had an easier time keeping my thoughts in order if things similar to State or Import Statements were organized in a way that I was already familiar with.
IN PRACTICE…When working with a React-Redux flow, you’ll want to make sure that:
- action creators dispatch proper actions by type, and return the correct values (whether you call them payloads or not)
- reducers reference the CORRECT_ACTIONS <=(that syntax)
- reducers pool together with combineReducers
- index.js imports Provider from react-redux, createStore and applyMiddleware from redux (along with anything else you might need)… thunk (almost definitely thunk if you’re making any asynchronous requests) from redux-thunk… and a rootReducer or the index of all your pooled reducers
- a store is created as a const and then passed to the store variable on provider, in order for your entire app to have access to dispatch and the reducers which manage state
- WHILE TESTING/BUILDING: you will want to have three files open at any given time: the component/container you’re working on, the reducer file (or files) that mapStateToProps makes use of, the action file that houses the actual actions index which you access with mapDispatchToProps
- YOU HAVE A DECENT THEORETICAL UNDERSTANDING OF WHAT IS HAPPENING BEHIND THE SCENES. (*note: you might not really need to know, but having struggled so much for two weeks trying to work through redux as a matter of syntax, I have the impression that being able to understand the pattern is more important. Once I finish up the app, I intend to report back with additional findings. UPDATE: I’m not yet finished with the app, but having this theoretical understanding, has made understanding syntax easier.)
In the meanwhile, I hope this was helpful.