DEV Community

Discussion on: Why React Needs Redux

Collapse
 
martinhaeusler profile image
Martin Häusler

I fully agree with the problem analysis in your post. I am using React/Redux in several projects, and it's most likely the cleanest UI code I have ever written.

However, react-redux has its own set of problems and hick-ups. Bear in mind that, even though you may save some typing when calling a "connected" component, the data dependency still exists; it's just hidden, it did not disappear. What we just introduced is a dependency of a component to something other than its props and its own state. It's a dependency to the store. That actually conflicts with the original design idea of React ("render as a pure function") because you add more data "through the back door". You may argue "but it still works!". Fair point. But did you ever try to implement shouldComponentUpdate with something other than return true;? Think about it. You want to bail out of updates as high up in the component tree as possible to save on computation/rendering time. However, you don't actually know the dependencies of your children (or grand children or...) because they might get their data from the redux store. The sad fact is: you can't know that, because component nesting is recursive. You can't even hard code it because you don't know what your children will be tomorrow or in two months. React-Redux breaks one of the core assumptions of React. Beware of that when you code.

Also, many of the pre-made React components you can pick up on the NPM repository are not ready for a React-Redux treatment; they do not implement the "controlled component" idea. Either they do not offer the required callbacks, or do not implement them properly (i.e. they still hold internal state). I usually end up rewriting almost every component myself. I had a look at quite a few React component libraries; and none of them seemed suitable for React-Redux at that time.

Collapse
 
ross profile image
Ross Creighton • Edited

Thanks for the thoughtful reply, Martin.

What we just introduced is a dependency of a component to something other than its props and its own state. It's a dependency to the store. That actually conflicts with the original design idea of React ("render as a pure function") because you add more data "through the back door".

I would argue that connected components still "render as a pure function". The connect HOC of react-redux creates a container component behind the scenes which wraps the original component and passes data to it as props. The component that we wrote is not modified, only wrapped. It still depends strictly on its props and state. A connected component can easily be used as an unconnected component with no changes to the code.

You make a good point about shouldComponentUpdate, although this is not a problem I have encountered frequently. My personal approach to avoid problems like this is to keep the component hierarchy as flat as possible and have components depend on data exclusively from the store. This way each component can decide for itself if it should update. I'm curious in what situations you have encountered the shouldComponentUpdate problem?

I certainly agree with you about pre-made components, I almost always implement my own, but I'm not sure I'm comfortable blaming that on Redux. When I have tried to use pre-made UI components in any system, not just React apps, they have usually ended up being more trouble than they are worth.

Thanks again for your reply, you've given me lots to think about :)

Collapse
 
martinhaeusler profile image
Martin Häusler

Hi!

About the connect function: I fully agree that no harm is done by this function in and on itself. It's a nice way of separating the "dumb" UI code that does nothing else than the rendering from the logic that connects the UI with the store, that's perfectly fine. The issue lies within the fact that the connected component has an additional source of information (the store). If you have a junior developer using your component, they might not be aware of this fact.

In 99% of all cases, it simply doesn't even matter, I give you that. It's mostly an "academic" concern. However, the moment you employ connected components in your application, you absolutely should not use shouldComponentUpdate anymore. The reason for that is that you can never be sure which child components your component at hand will have in the future. Today, your child components might be "dumb" react renderers (stateless components in the ideal case). However, tomorrow, in the third nesting level, someone might sneak in a connected component. From that point onward, your shouldComponentUpdate function will potentially prevent an update that was actually needed by a child. This introduces very subtle bugs that are extremely hard to detect by the developers because they seemingly occur "at random". At least that's what your users will tell you: "Sometimes this thing here doesn't update". And good luck in figuring that out. If you use react-redux, every time you implement shouldComponentUpdate, you make the implicit (and very strong) assumption that all your children, now and forever, will be pure, non-connected components. There is no way to enforce that in the react API, and somebody eventually WILL break this assumption. Maybe you yourself because you haven't touched this code in a long time, or maybe the junior dev next to you, but somebody will. From the point of view of that person, they don't do anything "illegal", they just attach another component to a parent component.

So, why bother, if you can just skip shouldComponentUpdate? Well, because it's a very important tool for optimizing react apps. React is fast in rendering, no doubt about it. However, if you are writing really large applications where a react component tree consists of hundreds or thousands of components, you will eventually need to optimize it, and you lose this very important tool.

I'm writing react-redux apps myself. It's not a deal-breaker. But it is something that we as react devs absolutely need to keep in mind. It is a problem, and I'm not sure if there is a solution to this at all.

Thread Thread
 
ross profile image
Ross Creighton

I think those are good points. There are always trade offs.