Reactlandia
Published in

Reactlandia

Redux-First Router data-fetching: solving the 80% use case for async Middleware

your routesMap configuration — notice the thunk option

THE 80% USE CASE FOR MIDDLEWARE

The 80% use-case for async middleware is dispatching 2 actions in sequence: the synchronous “setup action” ™ and an asynchronous “follow-up action” ™.

COMPONENT-PAIRED vs. ROUTE-PAIRED DATA DEPENDENCIES

WHEN DO YOU NEED COMPONENT-PAIRED DATA?

AD-HOC FETCHING IN COMPONENTDIDMOUNT

Fetching data in componentDidMount is the modern incarnation of the fat views/controllers anti-pattern.

The problem has been we have had no good designated place for “controllers” …until now.

ROUTE-PAIRED DATA FETCHING

Is all the information I need in the URL or cookies?

ASIDE: UNIVERSAL SPLIT RENDERING > SPA

BACK TO BUSINESS

componentDidMount WITHOUT APOLLO

✓ DERIVE STATE FROM THE URL— WHAT ABOUT MIDDLEWARE?

Even though Redux-First Router includes a middleware, it’s important to think of it as something simpler than that.

In other words, the vast majority of the time you simply want to set an initial state, and then set a second state depending on how the data fetching job went.

2 routes in Redux-First Router — one dispatch in your thunk (aka “follow-up action”)

GREAT JUSTICE (DECLARATIVE > IMPERATIVE)

When you can distill solutions down to config objects, rather than ad-hoc code, you achieve great justice.

ASIDE: COOKIE SESSION STATE

REDUX’S CONTRACT REVELATION

Any time I’m tempted to dispatch consecutive synchronous actions, I instead figure out how to make my reducers respond correctly as if only one of the actions was dispatched.

In other words, component-level dispatches is the #1 cause of multiple synchronous dispatches, and ultimately crummy rendering performance + a disorganized redux architecture.

URL-MANAGEMENT OUT OF THE WAY

QUICK, ANSWER THIS: how do we trigger the loading spinner until ENTITIES_FETCHED is dispatched?

TAKEAWAY

When you see a thunk corresponds to a URL (say your /login path), and because of that you know it’s the only thunk that can handle that URL, you know exactly what to expect of that thunk. And you know no other thunks can deal with it.

HOW DID WE GET WHERE WE ARE TODAY

In MVC terms, React is the V, Redux the M, and RFR the C.

As in the initial RFR pre-release article, it’s been a case of getting lost along our way as new things opened up the pandora’s box of options.

FINAL COMPARISON

If you made it this far, you deserve a break; play this song while you review the code comparison that follows (i.e. the real meat of this article)

Old componentDidMount + react-router + redux-thunk way vs. RFR way:

OLD componentDidMount WAY
NEW REDUX-FIRST ROUTER WAY
after looking at RFR’s route-centric approach, it barely makes sense to update your store from components anymore (unless it’s onClick/etc)
old loading reducer
new loading reducer + category reducer

“You should not read the location state directly from the Redux store. This is because React Router operates asynchronously (to handle things such as dynamically-loaded components) and your component tree may not yet be updated in sync with your Redux state. You should rely on the props passed by React Router, as they are only updated after it has processed all asynchronous code.”

CONCLUSION

UPDATE (July 23rd): Reselect has been implemented for the isLoading indicator and the videosByCategory reducer simplified by breaking it into an additional reducer: category. So this article won’t reflect exactly what’s in the CodeSandbox, but it will be a good learning transition, as I didn’t initially want to introduce Reselect.

> REPO:

> For more idiomatic javascript in Reactlandia, read:

--

--

The React Stack: Idiomatic Javascript in Reactlandia

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store