12 ms·
If plain, idiomatic React so great, why does every semi-complex React app end up bringing in a separate state management framework like Redux or MobX? The reas
by stupidcar 8y ago
If plain, idiomatic React so great, why does every semi-complex React app end up bringing in a separate state management framework like Redux or MobX?
The reason is that while you may be able to break up your HTML into a composable hierarchy of purely-functional components, the actual data and state you need to distribute to them has a structure that is completely unrelated to how its laid out in the DOM. In a complex web app, a component nested twenty levels deep may need to display pieces of information, like the user's date of birth and the current temperature on Mars, that none of its parent controls cares about.
At that point, you can either bite the bullet and pass state through layer upon layer of props, completely eliminating any semblance of separation of concerns in your component layering, or inject state into your components via some other mechanism, like Redux/MobX/Context. At which point, JSX is basically just another fancy HTML templating library.
"Idiomatic" React is a fun game to play when doing basic examples, using something like a todo manager, but as soon as you're in the real world, you hit its limitations very quickly.
- smackay 8y agoFor me (Vue + Vuex) the choice was simple: you get undo for free. Having a shared store really does change the way you look at web apps - it's almost a completely different paradigm. If you can avoid re-loading the data for a view if you already have it then then opening a new view to edit a subset of the data instead of dealing with popup makes life so much easier - you get a lot more freedom with the UX and going back to the previous view with the parent data is almost zero-cost.
- ilovecaching 8y agoYou can have undo for free using React as well. React doesn't care about how you manage your state changes, and it will selectively render only the parts of your app that changed.
- drb91 8y agoNot to mention, I believe time travel is an officially supported functionality for redux, if you choose to use that.
- boubiyeah 8y agoBut now you have a new problem: Managing the freshness of that cache.
- allover 8y ago> If plain, idiomatic React so great, why does every semi-complex React app end up bringing in a separate state management framework like Redux or MobX? Sadly it seems that's mainly been cargo-culted. It's not the case that React+Redux is the equivalent to say Angular, but by some unfortunate accident due to Facebook's announcement of Flux, and then the hype around Redux as a 'better Flux', people started assuming React+Redux is what is needed to build a React app. Meanwhile Dan Abramov, Redux creator says [1]: > Flux/Redux is meant for big apps with complex nested UIs that have many independent parts but share common caches of data. That's not "every semi-complex React app". In most "semi-complex React apps", most state can be derived from the route (e.g. react-router) or is relatively local. Redux is not required. [1] https://twitter.com/dan_abramov/status/732719257579065345 https://twitter.com/dan_abramov/status/732719257579065345
- ilovecaching 8y agoAgreed. Cargo culting is the main issue. The solution is to try and remain unbiased, and not look for direct synonyms between two very distinct approaches to managing user interfaces.
- olfactory 8y agoWell, FWIW js is not the most friendly language for functional programming. I'd argue that the trend toward immutable.js and redux occurred partly because rest/spread syntax was/is relatively confusing, and so immutable patterns without a library feel less elegant until one really groks the somewhat visually opaque semantics of the rest/spread syntax. Redux also offered a simple approach to the "action bus" idea from Flux, but omitted first class async support, etc. React itself also somewhat overlooked async patterns, which created the idea that their absence was by design and so an additional (opinionated) library was appropriate. In sum I'd argue that React actually fights against js quite a bit and that it will truly come into its own once reason gets more mindshare. For those of us who invested heavily in react as all this was becoming clear (and being ironed out) I hope we learned enough to allow better decision making in the future. Also, React has a few "on by default" performance enhancements that are a bit conceptually confusing and create something of a mismatch with the functional approach. But still it's difficult (and unpleasant) to imagine the world without React.
- DougBTX 8y agoReact was advertised from the start as the V in MV-whatever, so that seems like an overly restrictive definition of "idiomatic". > At which point, JSX is basically just another fancy HTML templating library. JSX is optional syntax sugar; my team uses React and Redux heavily, but we've opted not to use it. HTML templating is great actually, all the rendering is data -> UI. If you go back to the early Rethinking Best Practices presentation[0], it boils down to asking why client side development isn't like like HTML templating. The answer is that updating the entire page DOM on every change is unworkable, there needs to be support for partial updates. That's what React offers, a return to the data -> UI paradigm, without having to write a secondary code path for partial updates. [0] https://www.youtube.com/watch?v=x7cQ3mrcKaY https://www.youtube.com/watch?v=x7cQ3mrcKaY
- acemarke 8y agoOut of curiosity, what are you using instead of JSX? Plain `React.createElement()` calls, `createElement` aliased to a shorter variable like `e`, or something like the `react-hyperscript-helpers` library?
- spiritcat 8y agoit's funny how originally jsx is what kept me away from react, and now it's what keeps me from leaving.
- interlocutor 8y agoYou can actually leave react and still keep JSX. This tiny library lets you use JSX as a templating mechanism: https://github.com/wisercoder/uibuilder https://github.com/wisercoder/uibuilder
- kibibu 8y agoIt's funny how everybody hated E4X when Adobe and Mozilla were doing it, and love JSX now.
- 8y ago
- aylmao 8y ago> as soon as you're in the real world, you hit its limitations very quickly. Isn't a good chunk of AirBnB, Facebook, Instagram, Netflix, The New York Times and Dropbox written in React? The built-in state management has limitations, of course. I see it best for keeping state relevant to display-- React is supposed to be a "view" library, not a state management one.
- mateuszf 8y agoAnd also Office 356
- Too 8y agoBoth Airbnb and O365 web apps are horribly slow in the browser and hasn't had any noticeable feature growth in the past 4 years so i wouldn't use these as good examples of neither performance nor productivity.
- heyoni 8y agoIs there a way to tell or are we going by what these companies disclose?
- shados 8y agoUse the react devtools when looking at those websites.
- ng12 8y agoActually that's my favorite thing about the Redux model. The vast majority of our codebase is comprised of simple idiomatic React components. Our reducers and glue code (e.g. @connected containers) are a very small portion of the codebase. If I woke up tomorrow and decided Redux was the source of all our problems I could completely remove it while only needing to refactor a small portion (<5%) of our codebase that's mostly boilerplate anyways.
- ilovecaching 8y agoSo I see where you're coming from. To first address Redux, etc, React has no opinion on state storage, it's a feature not a bug. Obviously you need to store state somewhere, and Redux, Relay, etc are just tools to address that concern. But that's really unrelated to what you're trying to address, which is coupling between leaves that have shallow common ancestors, but are themselves quite deep. Although in my experience a good website does group related pieces of information, and so well organized state often maps easily to a well organized UI, functional programming gives us the tools to avoid deeply nested expressions regardless of your application (or even your framework). One thing to realize is that you always get to decide on the granularity of your compositions. It is not necessary to build a deep hierarchy if you design the granularity of your interfaces correctly. Another great tool is higher order functional programming, such as passing components to components (via children). In this way, it is easy to describe generic interfaces and supply specific pieces of data without having the intermediary interfaces know or care about that data. Another approach, akin to using something like the state monad, is to use Reacts context feature, but this is rarely needed, in my experience. Personally I make heavy use of higher order components, and I find I rarely exceed a component tree height of three.
- porker 8y agoIs there a blog post explaining higher order components in more detail, preferably with examples?
- kalkut 8y agoThe doc is very detailed with good examples : https://reactjs.org/docs/higher-order-components.html https://reactjs.org/docs/higher-order-components.html
- akie 8y agoHigher Order Components are like Aspect Oriented Programming - it takes a component and adds some stuff to it. It can add that stuff to any kind of component. That's all you really need to know. Examples of HOC are the connect() call from Redux, or the withNavigation() from React Navigation, or injectIntl() from React-Intl. These respectively add Redux functionality, navigation functionality, and internationalization functionality to your component. I think the name "Higher Order Component", like many things in the React world, is poorly chosen and actually obscures what it is, how it works, and makes it look more intimidating than it really is. It's technically correct (like 'reducer' is), but communicates nothing.
- strken 8y agoReact isn't about JSX and passing foo/onUpdateFoo down 20 levels of props. It's about data flowing in one direction down a tree of diffable virtual components, then being passed back up. The single most important idiom is that all data for a component should come from state or props, and that when you need to break this rule you should do it inside a single component or a handful of components that will then handle your global state management. I understand that such an open-ended product is frustrating to use because redux is insanely overengineered, mobx reintroduces data binding, and context is buggy and terrible, but I don't think what you're calling "idiomatic React" is actually considered idiomatic by anyone, including the core development team.
- chrisco255 8y agoRedux is not over-engineered. It's a simple library that's <1000 lines of code. It is great for large, complex apps where state gets hairy to manage. It's a bit verbose for smaller apps. But just because something is verbose does not mean it's over-engineered. It is explicit in defining all the possible states your application can get in. That's useful for a certain class of application.
- strken 8y agoIt might have been more accurate for me to have said "the code you will get if you follow the reference implementations and documentation of Redux will be overengineered". I dislike three things: that dispatch isn't usually made globally available, but is passed through context, which makes it effectively global anyway; that asynchronous actions are only available via plugins despite being a core part of JS development; and that dispatching an action is just a more complicated way of calling a function. Interested in hearing what you think, though. My Redux experience has been more limited by trying to avoid it on small projects.
- acemarke 8y agoHi, I'm a Redux maintainer, and I'd like to clarify a few things. First, your points about `dispatch` and `context` are specifically about the React-Redux bindings, not the Redux core itself. React-Redux is specifically intended to act as an abstraction layer so that your own components are "unaware" of Redux, which keeps them more reusable and more testable. It also saves you from needing to write store subscription handling every time you want to make use of data from the store. My "Redux Fundamentals" workshop slides [0] show examples of what it would look like to hand-write store subscription code all throughout your UI, and it would be a pain. If you _really_ want to, there's nothing stopping you from importing the store globally across your application and using it, but that misses out on the benefits of React-Redux, and also ties you to that one specific store instance. Second, you can absolutely do async logic without any middleware. However, one of the key design points of Redux was to allow users to choose which approach they want to use to handle async logic, without limiting users to whatever was built in to the core. I discussed this in my "Redux Ecosystem" talk at ReactBoston last year [1]. You can certainly do async logic without any special middleware - just `connect()(MyComponent)`, throw in a `setTimeout`, and call `this.props.dispatch()`. The point of `redux-thunk`, the most common async middleware, is that it provides a generic way to move async logic outside of your UI and make it reusable [2]. Finally, the "dispatching an action === calling a function" comparison can be true, but only if you're using Redux with a limited mental approach and treating actions like "setters". If you start thinking about actions as more of an "event that occurred", then that leads to having multiple parts of your reducer logic independently respond to the same action and update their own pieces of state (which is an encouraged usage pattern). Justin Falcone had some good thoughts on this a while back [3], and I talked about this some in a fewmore of my blog posts [4] [5] [6]. [0] https://blog.isquaredsoftware.com/2018/06/redux-fundamentals-workshop-slides/ https://blog.isquaredsoftware.com/2018/06/redux-fundamentals... [1] https://blog.isquaredsoftware.com/2017/09/presentation-might-need-redux-ecosystem/ https://blog.isquaredsoftware.com/2017/09/presentation-might... [2] https://blog.isquaredsoftware.com/presentations/workshops/redux-fundamentals/side-effects.html#/4 https://blog.isquaredsoftware.com/presentations/workshops/re... [3] https://medium.freecodecamp.org/whats-so-great-about-redux-ac16f1cc0f8b https://medium.freecodecamp.org/whats-so-great-about-redux-a... [4] https://blog.isquaredsoftware.com/2017/01/idiomatic-redux-thoughts-on-thunks-sagas-abstraction-and-reusability/ https://blog.isquaredsoftware.com/2017/01/idiomatic-redux-th... [5] https://blog.isquaredsoftware.com/2017/05/idiomatic-redux-tao-of-redux-part-2/ https://blog.isquaredsoftware.com/2017/05/idiomatic-redux-ta... [6] https://blog.isquaredsoftware.com/2017/01/practical-redux-part-8-form-draft-data-management/#improving-the-pilot-deletion-logic https://blog.isquaredsoftware.com/2017/01/practical-redux-pa...
- drb91 8y agoState management seems like inherently a different problem to solve than the problem React solves. What front-end framework out there has a single state management pattern that works for all sizes? It’s easy to point out frustrating things or hard problems; it’s not easy to point to a way out. Personally I love the explicit state flow react forces, and I would hate to move to a framework where I spend time figuring out how data goes from point A to point B.
- baddox 8y agoIdiomatic React is both compatible with and orthogonal to state management libraries like Redux or MobX. React is (in my opinion, and likely in the opinion of its creators and maintainers), a library for creating reusable ("dumb" or "presentational") components. In many web apps built with React components, you will want another library to manage the global state of the entire application and provide your dumb components with read/write access to specific pieces of that global state. I don't understand your point that injecting state into your components (e.g. with Redux' connect function) means JSX is just another fancy HTML templating library. All you need to do is have your React component export a "dumb" version as well as a connected version. Your dumb version will still be reusable in other parts of your application, and any other application could also use your dumb component and connect it to their global state through whatever means they please.
- mrinterweb 8y agoI've felt the same way. Vuex, Redux, MobX, or other application state libraries, all help in the event when passing data down through components that don't care about the data they are passing along becomes tedious. I like the general idea of "data down, actions up", but when it comes to separation of concerns, what is the point of a component taking parameters that it is just going to pass to a subcomponent? When components don't use the parameters in a meaningful way, the parameters are just noise. I came to this realization after passing the same parameters down about seven levels deep through components to question the mantra. I try to avoid shared and global state, but there are times that it just becomes very useful. It is important to now and again question if the dogmatic approach is pragmatic.
- spdionis 8y ago> seven levels deep There's your problem I think, as other sibling comments pointed out.
- pcstl 8y agoPeople mainly use Redux because they don't understand that React isn't Angular. React is meant to care only about UI state. Your application state should be kept separately, and React should just be a function from app state to UI. Redux is what you get when people try to use React as a "full-app" framework instead of what it's meant to be: a view layer.
- WA 8y agoSo how do you manage your application state? I‘m curious, because a search for such a phrase always brings up Redux, Thunks and Saga.
- pcstl 8y agoYou keep it out of React, manage it however you want to and is most convenient for your application's data model, and pass in the parts that are relevant to UI as props to React's root.
- kalkut 8y agoYou can make any suitable variation of the following pattern. You build a DataSource class/prototype with methods such as : - fetch - addChangeListener - removeChangeListener You extend this class for each data type : class CommentsData extends DataSource { // Your custom data source with your data treatment and data getters } And you use the Higher-Order Component pattern: https://reactjs.org/docs/higher-order-components.html https://reactjs.org/docs/higher-order-components.html
- tanilama 8y agoBecause async state management is a pain, and hard to reason about, that is what Redux and MobX are for.
- erikpukinskis 8y ago> the actual data and state you need to distribute to them has a structure that is completely unrelated to how its laid out in the DOM. It took me many years to realize this. I think very few front end developers understand this. And more problematically: very few framework devs seem to understand it. Stated another way.... Your tree of UI widgets, and Your tree of data which feeds those widgets ... are two orthogonal trees. If you are a front end dev and you haven’t spend time wrestling with that, I strongly recommend it. It’s extremely likely your front end architecture is suffering because of it. React take the strongest stance on this matter, by making the interface to every widget be one giant shared global. But globals are bad, so while it’s good they acknowledge the situation, they mostly punt on the question of how to deal with it.
- bryanrasmussen 8y ago>Your tree of UI widgets, and >Your tree of data which feeds those widgets Not with a well-designed XML format and XSL-T! But hmm, nobody seems to use that anymore either.
- mattmanser 8y agoHaving done this in the wild a while ago, it seemed to be hard for most of the other developers to do anything complex with it. You either really got it and then could do wonderful things, or you sorta muddled along with it and it was ok but it was like they were wearing a straitjacket. I made a pivot table control out of it, with almost all the logic inside the XLST, it was amazingly fast compared to IE6's javascript at the time. I remember that Blizzard used it for the WoW online character viewer which was streets ahead of what anyone else was doing. Also there's a DailyWTF about someone doing this on a large app, which brought the developer out of the woodwork to defend it who said in fact it wasn't a WTF, it was deliberate, it worked, loads of people loved it. Which prompted a huge debate about how it was actually kinda good, but just too high a learning curve (which is the death knell of many a tech). Personally I don't miss it. The best way I can sum up XML/XLST up is that it made me feel clever, and now I know that when I start feeling clever about my code that's a sure sign I'm making something that's going to be a nightmare to maintain.
- 11235813213455 8y agoredux isn't a framework, it's a very small library
- tomaskafka 8y ago> If plain, idiomatic React so great, why does every semi-complex React app end up bringing in a separate state management framework like Redux or MobX? Because React = state to DOM while Redux = how to get from previous state + action to a next state? :) They do different things.
- wehere1111 8y agoif walking is so great, why does every semi-long distance end up requiring a car or bicycle?