5 ms·
For all the people who use redux - a question - how is redux better (for your use case) than just a global variable?
by forgottenacc57 10y ago
For all the people who use redux - a question - how is redux better (for your use case) than just a global variable?
- acemarke 10y agoLots of reasons: - Isolation of "write logic" means you know where to look to see what code is updating a given chunk of state - Consistent state handling means it's a lot easier to think about what's going on in the application - The DevTools show you a log of dispatched actions, and enable you to step back and forth between states to see what the UI looked like at each point - Middleware lets you centralize app-wide logic, such as consistent transformations for AJAX responses - Redux's constraints (such as wanting state to be serializable) enable a number of other use cases, such as persisting state across page reloads and synchronizing multiple stores remotely. - There's a rapidly growing ecosystem of addons and utilities for specific use cases (see https://github.com/markerikson/redux-ecosystem-links https://github.com/markerikson/redux-ecosystem-links )
- forgottenacc57 10y agoI've built a pretty large react app and never needed these things. Things like stepping back through state seem honestly to me to be a gimmick not worth the required investment of time and pain.
- acemarke 10y agoI've seen a number of people make comments to that effect, and I genuinely don't understand that point of view. I use time-travel debugging on a daily basis, and it's a _huge_ time-saver for me. I also don't understand the "required investment of time and pain" comment. I've got a couple lines in my store configuration that sets up the Redux DevTools extension, and after that, It Just Works (TM). In fact, one of the posts in my "Practical Redux" tutorial series shows how to configure it: http://blog.isquaredsoftware.com/2016/11/practical-redux-part-3-project-planning-and-setup/ http://blog.isquaredsoftware.com/2016/11/practical-redux-par... .
- linkmotif 10y agoIt helps you sieve the global variable so components get just the data you say they should get.
- deleted 10y ago[deleted]
- kentor 10y agoReducers are pure functions so they can be tested very easily. Also the whole middleware thing and redux logger are awesome.
- borplk 10y agoIt is conceptually like a global variable except changes to it are strictly controlled. So in that sense it is a very close representation of reality. The reality is that the state of your application can be (and I'd say should be) perfectly presentable in a giant object. Redux is not shy about that and doesn't try to hide or escape from it. The importance is in how you manage reads and writes.
- Sacho 10y agoRedux has several components - actions, reducer(s) and the store. Why actions? Actions give you an explicit API between the global variable manager(the store) and your components. For one-off components that are cognizant of the fact they're part of an "App", this isn't very useful - e.g. if you want the component to insert "foo" instead of "bar" into your global state, you just go and modify it. For reusable components, however, their interface may be locked(used by other parts of your app or even different apps!). Then you need some kind of adapter to turn the "foo" they give you into a "bar" - actions are one such adapter. Besides that, actions are one part of the "state machine" design that redux implements. Actions enumerate the possible ways your state can change. Is your state meaningful if you change global.foo = "bar"? It might be, or it might not. Actions are a contract between those modifying the state and those consuming the state, that all changes to the state will leave it in a coherent...state! Even MobX, which essentially takes your "global variable" idea and runs with it, advocates for actions. Having this guarantee is great for debugging. Is the global state mangled? The global state manager code must be broken, since everyone sends actions, and the only one consuming the actions is the manager. You don't have to hunt for a rogue component that's setting global.foo = "bar" instead of global.foo = "baz". Once your global state manager is ironed out, your problems are less "why is my state mangled" and more "why isn't the component sending the expected action". In theory, this should simplify your debugging a lot - you are not trying to disentangle a complex set of interactions that led to your state being mangled and a component failing from that, but rather you're just looking for the one component that isn't sending its actions properly. Redux's debugging tools try to highlight this, with the action logger and so on. In practice, how useful this is depends on how you've designed your actions and global state manager. It is entirely possible to write a trivial global state manager and essentially place all your logic in the actions(for an extreme example, imagine a state manager that accepts an action "set" with a "key" and a "value" - you haven't actually gained anything then!). Why reducers? If you're convinced that a global state manager and actions are a good idea, you are now stuck deciding how exactly to implement this manager. Let's say you have a yet-unwritten global state manager. You know the current global state, and you've just received an action. A reducer is function with the signature (state, action) => newState, essentially implementing a global state manager! Redux goes a step further and asks that reducers are "pure functions" and that the state is immutable and replaced instead of modified. The reasoning here isn't specific to Redux and it's once again related to consistency and debugging. Do you really need all of this? That's a good question, and I think it really depends on the project. You may have heard people advocating that you don't use any local state and put everything into Redux. This attempts to solve the "reusable component communicating with others" issue, which by the way I don't think Redux solves well(there's tons of 3rd party libraries trying to deal with that). For this specific case, I think "global variable + event emitter" is a decent solution. What about more complex state interactions? Well, for them I think the concepts Redux introduces are incredibly useful - not having to worry about your state's consistency is a huge help in debugging. Does Redux itself really deliver them 100%? Well, quite often a lot of your state changes will be coupled with side effects, ranging from animations to API calls. Without carefully designing your reducers, the side effects will quickly eat up any benefit - you may be stuck debugging "why doesn't my action creator pass the appropriate action to my trivial reducers". This is a point that Redux doesn't really handle - there's lots of middleware, addons and full-blown libraries trying to deal with the issue(e.g. redux-thunk, redux-saga, and so on). My personal opinion is that the concepts that Redux tries to introduce are very useful to know and keep in mind when designing your system. Whether you should commit to Redux the library(and its accompanying middlewares and so on) is a different decision. I think I've learned a lot from studying Redux and thinking about the concepts it tries to introduce. However, all the benefits Redux provides depend heavily on the design of your actions and reducers. With a poor design, you are stuck adding more boilerplate for no gains. This is why I wouldn't use it in many of my projects - I don't think I have the experience to design my state management in such a way as to extract significant value from Redux, without being bogged down by the extra boilerplate.
- ricardobeat 10y agoReturning a new object whenever data changes (poor man's immutability) gives you time travel / replay / undo, and makes debugging straight forward. All data changes happening in the reducers decouples the UI actions from business logic. Redux only looks complicated because it tries to gracefully catch every possible user error, and has a bit too many layers of functional abstractions. You can implement the whole thing in a few dozen lines of code.