Live data from Hacker News

Idiomatic Redux: Implementation and Intent

blog.isquaredsoftware.com

21–30 of 88 posts

Re: Idiomatic Redux: Implementation and Intent

#21
I've just started another side project using React with redux. One of my goals is to keep my code as simple as possible while still being able to build a large application.

To keep it simple, I'm not using react-redux (I often try to avoid this), and I generally pass the entire store down through all child components, again to keep it simple. My top level app with its simple navigation code subscribes to the redux store and sets its state from it. My router is just a bunch of statements like {pageName === 'connnections' && To avoid too much boilerplate, I find most of the time all you need are some helper functions. I have a helper function called 'action' that I call like action('LOAD_SOME_DATA') that dispatches on the store with type: 'LOAD_SOME_DATA'. I use a simple 'getIn' function to access nested data, and I mutate data in my reducers with object-path-immutable. Everything is clean and easy to read.

I believe one of the biggest problems with the React community is the constant bleed of 'performance' into app design and development. Premature optimization is everywhere.

Guess what, most apps won't need immutable data and free componentShouldUpdate checks, memoized selectors, or subscribing to subsections of the store using complicated 'connect'/high order component plumbing.

The one time I actually had a perf issue with React was when I had a GIGANTIC list of data (showing all the active salespeople in our company -- we have a lot), which due to me storing form state in redux was being completely re-rendered every keystroke.

The solution wasn't to add react-redux or start using immutable data - it was to add paging and filtering. I improved performance, but more importantly, the UX of the app with this.

If your React app really is so huge and complex that it needs reselect, react-redux, react-router, great stuff -- you are obviously building software for a successful product with lots of feature requirements. Most apps I've worked on never got to this level of complexity.

Re: Idiomatic Redux: Implementation and Intent

#22
post #9

Whenever a Redux thread pops up, there's inevitably complaints about "boilerplate". I'd like to pre-empt those complaints a bit by pointing out that, per part 2 of my post, it's entirely up to you how much abstraction you use in your own Redux app. If you want use Redux for a particular use case, someone has probably already written an addon or utility to help solve that problem, and I've got them listed in my Redux…

Mobx is an alternative. Simple and less boilerplate.

Re: Idiomatic Redux: Implementation and Intent

#23

This article serves only to reinforce that the beautiful simplicity of react is spoilt by the confusion of Redux. I feel that every Redux blog post should start by pointing out that despite react/Redux almost being discusssed synonymously, as the author of Redux points out, "you might not need Redux". I would go further and say "avoid Redux until you know you need it", and point people to more simple ways of reaching…

>Redux is a power tool for experts that is disheartening beginners and sending them down the wrong path. I've seen this expressed many, many times, and it is something that I've honestly never quite understood. I started with React less than a year ago, and it wasn't until I added Redux to my stack that I began to feel perfectly comfortable with, To me, the fact that actions dispatched in whatever component would cau…

Redux is conceptually simple and really helps in attaining a highly decoupled and resilient architecture, but it shares the same configuration-over-convention mindset as the rest of the js/node world. Once you get all the little modular pieces assembled just right, it's great to work with, but it can be quite a struggle to reach that point. There are also a bunch more libraries you need beyond just redux to make things really hum the way they're supposed to.

Re: Idiomatic Redux: Implementation and Intent

#24

This article serves only to reinforce that the beautiful simplicity of react is spoilt by the confusion of Redux. I feel that every Redux blog post should start by pointing out that despite react/Redux almost being discusssed synonymously, as the author of Redux points out, "you might not need Redux". I would go further and say "avoid Redux until you know you need it", and point people to more simple ways of reaching…

Redux itself is boilerplate heavy but conceptually pretty easy to understand. But once you start building real world apps and have to deal with async actions things get a lot more complicated and a lot of the benefits of the redux model evaporate. I plan to use mobx on my next react app.

I went from Redux to MobX in one of my recent projects and it was a breath of fresh air. It's so much easier to work with, and more performant in my situation, too.

Re: Idiomatic Redux: Implementation and Intent

#25
post #9

Whenever a Redux thread pops up, there's inevitably complaints about "boilerplate". I'd like to pre-empt those complaints a bit by pointing out that, per part 2 of my post, it's entirely up to you how much abstraction you use in your own Redux app. If you want use Redux for a particular use case, someone has probably already written an addon or utility to help solve that problem, and I've got them listed in my Redux…

Mobx is an alternative. Simple and less boilerplate.

An underrated alternative, at that. I had a great experience transitioning from Redux to MobX.

Re: Idiomatic Redux: Implementation and Intent

#26
post #21

I've just started another side project using React with redux. One of my goals is to keep my code as simple as possible while still being able to build a large application. To keep it simple, I'm not using react-redux (I often try to avoid this), and I generally pass the entire store down through all child components, again to keep it simple. My top level app with its simple navigation code subscribes to the redux st…

Passing the store (or in general, your application state) down from each component to their children has one big flaw: It reduces your components' reusability in other projects.

You can circumvent this by creating a component at the top level of your application which holds the state and passes it down via React's context. The state-dependent components can then pull the state from context where they need it. By doing so, you basically reinvented react-redux, which works just like this (+ the performance optimizations).

Regarding your issue with the complete app rerendering on a single keystroke: This is a result of you passing down the entire store to each component. Since you still edit the store in an immutable way, on every keystroke you create a new store object and React rerenders everything because the store prop changed. I'm also confused how using paging/filtering would help with this.

Another advice would be to not store form state in redux. Keep your redux store only for your actual model application state. Keep forms/temporary state in your components and move it to your model redux store once it is done/baked.

Re: Idiomatic Redux: Implementation and Intent

#27
post #9

Whenever a Redux thread pops up, there's inevitably complaints about "boilerplate". I'd like to pre-empt those complaints a bit by pointing out that, per part 2 of my post, it's entirely up to you how much abstraction you use in your own Redux app. If you want use Redux for a particular use case, someone has probably already written an addon or utility to help solve that problem, and I've got them listed in my Redux…

Mobx is an alternative. Simple and less boilerplate.

This! I feel like a broken record the amount of times I urge people to try MobX, but genuinely I think everyone I know who has tried it has been so pleasantly surprised at how quick and easy it is to work with and use effectively, compared to Redux. Personally, I reckon I can build stuff out which uses a reasonable amount of state at least twice as fast with MobX, and the code feels more maintainable as there's less of it, which as a freelancer is huge.

That's not to say Redux is bad or there is no value to learning it though. It presents a really interesting take on state management and really opened my eyes to a huge amount of concepts. I'm just not sure I would want to go back to a heavy Redux project again having used MobX!

Re: Idiomatic Redux: Implementation and Intent

#28
post #11

When I first came to React my understanding was that React/Flux were all but a package deal, and that I better use Redux because it seemed so popular. Redux quickly became a pain point in terms of boilerplate and added cognitive load. Now a top level stateful component works for 90% of my use cases.I feel the same way about React Router. Maybe if you're building something quite large or complex these prepackaged tool…

I wouldn't recommend this at all. Sure if you have a tiny site with very limited functionality or you're learning react, you don't need redux. But if you're using components they way they're intended, (not cramming everything into a few overloaded components), you're quickly going to be passing down props down through layers and layers. It will quickly become a maintenance nightmare. Just imagine that you have a butt…

I actually find it easier to reason about my components when I can trace data sharing in my hierarchy rather than allowing components to cheat and circumvent sharing state in their common ancestor. I think it's idiomatic React to construct hierarchies of functional components topped by very few stateful components. Using connect() to turns components deep in the hierarchy into stateful components can only lead to a less declarative dataflow that tightly couples those components to Redux for very little gain.

If you're having difficulty moving components around because of state consider that you may be thinking too statefully and should try to find a less stateful way to describe your UI, or that the UI you have constructed does not adequately group related pieces of data and functionality together, which will lead to a confusing UX.

Re: Idiomatic Redux: Implementation and Intent

#29

I don't event want to open the article that has both of "idiomatic" and "tao" words in the title.

For what it's worth, "Practical Redux" is my blog series that demonstrates Redux techniques by building a sample app. "Idiomatic Redux" is my series for my own thoughts on why I think certain Redux usage patterns are good or bad. The phrase "Tao of Redux" was just something that popped into my head and sounded catchy, and seemed to go along with the idea of "explaining the Redux philosophy".

It sounds like the author is some kind of guru who became enlightened and willing to share the "tao" of "idiomatic" way of JS library. Can't you see how pretentious it it?

Re: Idiomatic Redux: Implementation and Intent

#30
post #21

I've just started another side project using React with redux. One of my goals is to keep my code as simple as possible while still being able to build a large application. To keep it simple, I'm not using react-redux (I often try to avoid this), and I generally pass the entire store down through all child components, again to keep it simple. My top level app with its simple navigation code subscribes to the redux st…

I'm _very_ curious: why do you feel you need to "avoid" React-Redux?

There was a similar thread on Reddit a few days ago, asking why the OP should bother using React-Redux [0]. I'll paste the main part of my reply:

> First, while you can manually write the code to subscribe to the Redux store in your React components, there's absolutely no reason to write that code yourself. The wrapper components generated by React-Redux's connect function already have that store subscription logic taken care of for you.

> Second, connect does a lot of work to ensure that your actual components only re-render when they actually need to. That includes lots of memoization work, and comparisons against the props from the parent component and the values returned by your mapStateToProps function for that component. By not using connect, you're giving up all those performance improvements, and your components will be unnecessarily re-rendering all the time.

> Third, by only connecting your top-level component, you are also causing the rest of your app to re-render unnecessarily. The best performance pattern is to connect lots of components in your app, with each connected component only extracting the pieces of data it actually needs via mapStateToProps. That way, if any other data changes, that component won't re-render.

> Fourth, you're manually importing the store into your components, and directly coupling them together, thus making it harder to test the components. I personally try to keep my components "unaware" of Redux. They never reference props.dispatch, but rather call pre-bound action creators like this.props.someFunction(). The component doesn't "know" that it's a Redux action creator - that function could be a callback from a parent component, a bound-up Redux action creator, or a mock function in a test, thus making the component more reusable and testable.

> And finally, the vast majority of apps built using React and Redux use the React-Redux library. It's the official way to bind the two together, and doing anything else will just confuse other developers looking at your project.

> So, part of the issue is you're not using React-Redux and connect, and part of the issue is you're using an inefficient pattern for pulling data from the Redux store into your React components.

So no, many apps don't need to spend tons of time optimizing performance, but at least part of that is because `connect` already handles a lot of that for them. There's also other reasons for immutability, per my original post for this thread: time travel debugging, testability, and ability to reason about state updates.

Also, in regards to the "re-rendering on every keystroke" issue, my post "Practical Redux Part 7: Form Change Handling" [1] shows off a React component I made that specifically helps buffer those for fast form updates, while debouncing the number of Redux actions dispatched.

[0] https://www.reddit.com/r/javascript/comments/6hperk/i_use_re...

[1] http://blog.isquaredsoftware.com/2017/01/practical-redux-par...

Post reply on HN