Friday, September 13, 2024

redux, redux: why people like and dislike it

I was doing some debugging earlier this week on frontend heavy with Redux.

For those who don't know, React (or almost any component based UI system) has a problem - how to share information between parent and child (and grandchild and greatgrandchild etc) components.

No right-thinking developer likes to admit it, but sometimes you kind of "need" global variables, or at least some kind of widely shared state - but raw global variables are horrible, you don't know where or what may change the information you're depending on, you have to be careful a child's local variable doesn't share the same name as something from the wider context, etc.

Now "React 101" tells how you can have a component passing data to a direct child via props. And "React 102" explains how to have call backs so the child can set things in the parent. But again, having to explicitly pass across generations as props - from greatgrandparent to grandparent to parent to child is burdensome.

Eventually, when React got Hooks it got Contexts - roughly speaking it's just a nice way of declaring regions for semi-global variables, but its usage is declared pretty explicitly, with useContext() pulling the shared information back into local state.

Before Hooks' introduction 4-5 years ago, Redux was the go-to choice to solve the "global variable" issue Last year's State Of JS is curiously silent about it's current happenings, but its usage and popularity were strong but declining in previous years.

I always thought there was a fair amount to dislike about Redux even when it was the only game in town - it tends to put the code path for a single interaction all over the place - declare an action in one file, have something like a button click dispatch that action in another file, have a reducer take the action and modify the global store in another file, then back in the component use mapStateToProps or a useSelector hook to see and act on the change. 

(This is a somewhat contrived example, since a single UI action should often be handled as local state to a component, but I've definitely seen examples like this in the wild! And in any event, even for stuff making good use of Redux there's still at least 3 files for anything involving this kind of shared action -> state change -> display kind of chain.)

But doing some debugging (I suspect the problem was probably based on data from the endpoints, but I wanted to get a better feel for why a button was being hidden) - I admit Redux's devtools are kind of neat:

You can see the actions on the left, and what the state was at each action's point on the right (plus you can pin a certain tree of the state and see just when it gets modified.) I think there are also tools to time travel to earlier states - which very much embraces the declarative programming paradigm, the idealized world of state goes in, full UI comes out.

You still need to do bread-and-butter debugging (sometimes it might not be clear just which action or reducers are in play) but it is clearly a cool tool to have around.

Another advantage to heavy Redux use is its middleware; if you have most of your site tooled with Redux, you can have, say, analytics middleware that just listens for the relevant action events and record then them - this was one of the approaches we landed on with this project, and was cleaner than having to insert a lot of "onclick" monitors.

No comments:

Post a Comment