11 ms·
Redux vs. The React Context API
- k__ 8y agoIf you just want to share state use context. Maybe use something like statty or unstated to remove some boilerplate code. Redux is nice if you need more predictable interactions, for example when you need undo.
- thawab 8y agoContext is great to work with and solves most of our usecases. I also recommend looking into Unstated[0], simple api and easy to implement. [0]https://github.com/jamiebuilds/unstated https://github.com/jamiebuilds/unstated
- shripadk 8y agoI use constate which is very similar to Unstated: https://github.com/diegohaz/constate https://github.com/diegohaz/constate
- MatthewPhillips 8y agoI'm not a React dev, but both approaches seem like they would make testing harder. Prop drilling must be the most testable approach. Am I wrong?
- meesles 8y agoYou're right, but testing the whole page's component functionality in large frontend apps isn't super common, either. In these cases, you would test the lower-level components and then not necessarily test their functionality for the whole page. The costs of deep prop trees 1) kills many performance benefits offered by a good react/redux setup 2) makes it hard to build off of the state (much like a monolithic codebase) because it can be harder to find if something is already there or not.
- antjanus 8y agoI'm a non-React dev but I wrote modern apps with Angular (and have written React). I think the best testable approach really is: 1. unit testing on the smallest bits (Redux actions/reducers make unit testing them SUPER easy) 2. do e2e with something like Cypress. Anything in between can be helpful but I found it can be too tedious, or difficult to do and ultimately, unit/e2e catches most things
- dceddia 8y agoI think this is a solid approach. I like to add snapshot testing for individual components too. The slowest tests to write for me are always the ones that involve some kind of async stuff.
- alangpierce 8y agoIt definitely makes testing a bit different. The downside to prop drilling is that you get components with lots of props, and it can be tedious to figure out how to render a component at all if you need to pass in 20 props for all of its transitive dependencies. The upside is that you have a clear list of the 20 needed props, and once you've figured them out, your component will work. With Redux and Context, you might have test setup code always populate the store with reasonable defaults for the 20 different data dependencies. Then, a typical test might update a few things in the store with test-specific values, render <Nav /> without the need to specify any props, and then perform interactions, inspect the results, etc. There's more going on behind the scenes, but it's also easier to get started because you don't need to figure out 20 props. (There are many, many ways to think about testing here, though, and this is just one approach.)
- williamdclt 8y agoThat's why most people say to separate the connected component (that gets few props) wrapping the unconnected one (that gets a lot of props). You usually test the unconnected. If you want to test the connected component, it's still good to separate them as you won't test the same things (correct props are passed down, rather than UI renders)
- alangpierce 8y agoMakes sense to test the inner unconnected component when you want a focused unit test on the component. FWIW, I greatly prefer integration tests (using JSDOM and enzyme) when working with React/Redux, since they're often easier to write than unit tests and give me much more confidence in the software, and they don't have the speed or reliability downsides that some people talk about with integration tests. Unit tests certainly have their place, though. As one (admittedly extreme) example, a while back I hit an issue where a refactor caused a very simple crash: just load the app, click a particular button, and it immediately crashes. All relevant components, actions, stores etc had extensive unit tests, but there was no test to make sure that the component dispatched an action that was compatible with what the store wants. I wrote an integration test for it, "load the app and click this button, and assert the intended effect", and it ended up being about 5 lines. It exercised the same code paths as the hundreds of lines of unit tests, and gives me much more confidence in the overall correctness of the system.
- deleted 8y ago[deleted]
- AlexCoventry 8y agoredux-saga-test-plan has a few warts, but it's made testing HOC interactions fairly straightforward for me.
- alangpierce 8y agoRedux contains a number of different ideas/solutions, and I think it's maybe more fair to view them independently. Redux solves prop drilling via the connect function (technically in react-redux, not core redux), and you might say that Context competes with that aspect. Other aspects of Redux are completely unrelated to Context and also good to understand: a unified immutable state tree transformed via composable pure functions in response to a well-defined set of actions represented as objects. Not that you can't do that with Context, but I think it's maybe unfair to view Context as a replacement for Redux.
- dceddia 8y ago> I think it's maybe unfair to view Context as a replacement for Redux. That pretty much sums up why I wrote this article :) After the new Context API came out, a lot of people started saying that it would replace Redux, and like you said, they only really overlap in that they can help avoid prop drilling. Redux is more powerful, out of the box anyway.
- bhj 8y agoDefinitely, the power of redux middleware should not be underestimated, e.g. redux-throttle[0], redux-optimistic-ui[1], redux-persist[2] [0]: https://github.com/mathieudutour/redux-throttle https://github.com/mathieudutour/redux-throttle [1]: https://github.com/mattkrick/redux-optimistic-ui https://github.com/mattkrick/redux-optimistic-ui [2]: https://github.com/rt2zz/redux-persist https://github.com/rt2zz/redux-persist (to be pedantic, some of these are not solely middleware)
- WalterSear 8y agoFunny, I vastly prefer the simplicity of passing down props over HOC spagetti - even when heavily nested. It is a simple matter to keep things organized and out of your way, and change detection is taken care of by selectors. I used to think props were good for dynamic components, but with portals available, I rarelyconsider them a good pattern for anything but components shared between applications. I use context to pass down actions. IMHO, mapping those into state should be deprecated.
- 8y ago
- jadbox 8y agoI really really like mobx-state-tree (which is way different from just mobx). I'm not sure where I'd use the Context API over MST, but I'm currently toying with comparing both. Offhand, MST seems to be friendlier to Typescript.
- AlexCoventry 8y agoThe typescript annotations for immutable.js do have a lot of limitations. I wound up writing a bunch of my own.
- solidr53 8y agoMST is a beast, I use it for everything. It great for abstraction, has good typescript support. tree based nodes are just a super nice structure for applications in general. I've used flux, redux, mobx, context, combinations of those, and I think I finally found something that will stay. If you haven't tried it, I highly recommend it!
- blahblahblogger 8y agoDo you use it with React Native?
- solidr53 8y agoHeck yes! https://github.com/birkir/hekla https://github.com/birkir/hekla
- lewis500 8y agoThis is great. Love the idea of passing components as props regularly. I have done this a few times before, but I guess in my head I still think of components as something "real" and so passing them down as prop data feels wrong somehow...but it isn't! Now that I have seen Dan Abramov bless it, I feel less guilty. Off to refactor...
- ncphillips 8y agoThis is a good article, but the title makes the wrong comparison: * Context is a dependency injection utility. * Redux is a state-management library. Redux doesn't know anything about React. In order to use it with React you need to use ReactRedux, which actually uses Context to do it's thing. The comparison being drawn with the article is still the old: > React Redux vs React State. The difference now is that React has a new (and substantially better) Context API.
- acemarke 8y agoYes, Redux by itself knows nothing about React. But, the vast majority of Redux users are using React, and it's a reasonable shorthand to just say "Redux" in this case. It's also how most end users would tend to refer to things. FYI, I'm a Redux maintainer. We are currently working on an internal refactoring of React-Redux's `connect` so that it will use the new `React.createContext` API instead of legacy context. We've got two open PRs with "competing" reimplementations, and I will actually be spending the rest of today hacking on those. The immediate goal is to make React-Redux at least compatible with React's upcoming "async rendering" capabilities. However, we do have some difficult problems to solve in order for Redux to take full advantage of the "Suspense" feature. We've got a decent idea what the problem space is, but we need some more examples and guidance from the React team so we can try to work on a solution. Side note: we're also hoping to completely rework the React-Redux docs (since they're mostly just a jargonistic API reference in a Markdown file in the repo), and we're also considering a restructuring / reworking of the core Redux docs as well. Would love to have some suggestions or even additional volunteers to help us! Issues/links for reference: - Roadmap: https://github.com/reduxjs/react-redux/issues/950 https://github.com/reduxjs/react-redux/issues/950 - v6 WIP PRs: https://github.com/reduxjs/react-redux/pull/995 https://github.com/reduxjs/react-redux/pull/995 , https://github.com/reduxjs/react-redux/pull/1000 https://github.com/reduxjs/react-redux/pull/1000 - React-Redux docs: https://github.com/reduxjs/react-redux/issues/1001 https://github.com/reduxjs/react-redux/issues/1001 - Redux core docs: https://github.com/reduxjs/redux/issues/2590 https://github.com/reduxjs/redux/issues/2590
- hajile 8y agoThe ReactReason devs seem to be averse to adding the context API (fears of instability). Does the Redux team have any similar reservations?
- dmix 8y ago> I’m going to assume you’ve got the basics of React down pat (props & state), but if you don’t, take my free 5-day course to learn the basics of React Gotta love the contextual marketing in a still-useful article. This made me realize content marketing combined with educational tools in an underrated small business idea, which I'm sure could apply to a hundred small niches when done right by legitimate domain experts.
- acemarke 8y agoAnd I can completely vouch for Dave's content, too. I frequently refer beginners to several of his articles to answer their questions. Highly recommended!
- stevehawk 8y agoYa. Like a lot of hacker news posts they are really just advertisements. I bought Dave's book a couple of months ago. It's overpriced in my mind (it's more like half a book and stops short of delivering what I think most people would expect or want, i feel) but he is a good writer and what is in the book is pretty informative and solidly instructional.
- jen729w 8y agoSame here, but I considered part of the purchase price to be a thanks for the many useful blog posts and, as a result, am very happy with my purchase. Thanks, Dave!
- dceddia 8y agoCheers, thank you too! Pricing is hard :/ Price too low, and people don't take it seriously. (e.g. $9 for 35 hours of video). Price too high and people run away. It was my first product, too. I looked at it as, "how many hours would this save someone?" Filtering through bad tutorials, just-in-time googling, all that stuff. Of course with front end there are a billion other learning resources out there, lots free, lots cheap. Hopefully the book is a more direct path than some of those others. Always room for improvement and experimentation of course :)
- dmix 8y agoIs there something equivalent to the Context API in Vue.js?
- nkings 8y agoprovide/inject allows dependency injection, though it is not meant for application state
- philliphaydon 8y ago> Is there something equivalent to the Context API in Vue.js? Don't think so, but I still feel like Vuex is better than Redux and Context API.
- jefflombardjr 8y agoReact Redux actually uses the Context API (Update: Old context api). "Context is what powers React Redux under the hood. The new context API isn’t to “replace Redux”, it just fixes a broken feature that needs to be provided by React. Whether you use it directly or through another API like RR is up to you" [0] At the end of the linked article the author states "Today, when Redux is more than you need, you can reach for Context." I'd actually argue the opposite. Redux, specifically React-Redux, is an abstraction. An abstraction that simplifies using the Context API. All I need to think about when using Redux is Flux architecture. There is excellent documentation around Redux, context api not as much. If you don't feel confident about Redux, or would like to get a better understanding of it, check out these three things (in order): 1. Understand Flux Architecture: https://facebook.github.io/flux/docs/in-depth-overview.html#content https://facebook.github.io/flux/docs/in-depth-overview.html#... 2. Understand Redux: https://egghead.io/courses/getting-started-with-redux https://egghead.io/courses/getting-started-with-redux 3. Implement Redux: Read the documentation at https://redux.js.org/ https://redux.js.org/. At this point you should have a good grasp on the concepts so pay attention to implementation details here like designing the state. [0]:https://twitter.com/dan_abramov/status/964946781493780480?lang=en https://twitter.com/dan_abramov/status/964946781493780480?la...
- timdorr 8y agoWe use the legacy Context API: https://github.com/reduxjs/react-redux/blob/47facdbcae2412d37d72fa5c37cb4e0cd64a9b4a/src/components/connectAdvanced.js#L139-L146 https://github.com/reduxjs/react-redux/blob/47facdbcae2412d3... This article is looking at the new Context API, which uses React.createContext() to create a Provider/Consumer pair of plain components. This has a number of differences in behavior, most critically around blocking updates incorrectly. We are looking to switch to the newer API in 6.0. We have two in-progress PRs for this: https://github.com/reduxjs/react-redux/pull/1000 https://github.com/reduxjs/react-redux/pull/1000 https://github.com/reduxjs/react-redux/pull/995 https://github.com/reduxjs/react-redux/pull/995
- jefflombardjr 8y agoVery cool, thanks for the clarification. To me, this is yet another perk of using RR on top of the actual api. As someone who works on a smaller team, updating our projects to use the new context api would be a significant undertaking. By using RR, the implementation details are left better equipped engineers, our team can focus on meeting business requirements.
- crooked-v 8y agoWhy not both? https://github.com/icopp/react-redux-provider-consumer https://github.com/icopp/react-redux-provider-consumer
- acemarke 8y agoSee the other comments in this thread from Tim and myself about updating React-Redux to use `React.createContext`. Also, as a side note: we're open to adding a render props-based API at some point in the near future, since there's a number of people who have expressed interest in that.
- crooked-v 8y agoSomething like the Consumer usage, and a way to apply it to arbitrary transformations of state (see the README on that repo for an example), would go a long way towards de-boilerplating a lot of things. The code I deal with has a painful number of connect() calls just for outputting pieces of data from the store.
- acemarke 8y agoMmm... not sure I really see a difference between that and what `connect` does right now. Can you clarify with a specific example?
- crooked-v 8y agoCompare... // with connect import { connect } from 'react-redux' import { defaultSomething } from 'src/store/ducks/something' const Whatever = ({ something }) => <div>{something}</div>; export default connect(state => ({ something: state.something || defaultSomething }))(Whatever); ...to... // with consumer import { identity } from 'ramda'; import { SomethingConsumer } from 'src/store/consumers' const Whatever = () => <div><SomethingConsumer>{identity}</SomethingConsumer></div>; export default Whatever; One more line in the second also goes away if the consumer defaults to an identity function if not given a suitable child. // with consumer import { SomethingConsumer } from 'src/store/consumers' const Whatever = () => <div><SomethingConsumer /></div>; export default Whatever; The boilerplate in the first case also gets much, much worse if you're using Typescript, as type inference gets wobbly at best with HOCs and so for even simple usage you have to also define out your "inner" and "outer" props for each component you want to use connect with.
- beders 8y agoHow do you test all this magic going?
- talkingtab 8y agoMy experience seems to be very different. I have used redux extensively for two years and love it. It is well thought out and solved a problem in a brilliant way. I have however, been ripping redux out of all of my projects, one by one and replacing them with the Context API. I remove file after file of actions, reducers et al and replace them with one context Provider. Someone commented that the power of redux should not be underestimated and that is absolutely true. It is also true that the complexity of redux should not be underestimated. My code bases have been greatly simplified. In my limited experience the Context API covers 80% of the use cases that required redux, with 80% less complexity. I am sure I will use redux in the future, and I am a better coder for having learned it, but my experience with Context has been very positive.
- cageface 8y agoI’ve had similar experiences. Redux is very elegant in principle but I’ve found that it results in an explosion of boilerplate and hard to follow code paths. By the time you’ve pulled in something like redux-saga to handle async the lovely simplicity that made react so popular in the first place is a distant memory. And the mess that an eager but inexperienced developer can make with this stack is truly something terrible to behold.
- sbr464 8y ago// Note that it's named with UpperCase, not camelCase Refers to Pascal case
- jinushaun 8y agoRedux solves the problem of managing state and state changes. Context solves the problem of passing props to nested components. Context doesn’t replace Redux because they solve different problems. This is also evident in the fact that Redux internally uses Context to pass props.
- gwillz 8y agoIt's quite trivial to hack your own react-redux using the new context api. It makes a lot of sense too - you get type safety, redux state management, and the redux dev tools. Although I do worry that old-mate react-redux hasn't transitioned yet for a good reason. Anyway, as soon as I realised that the two are complimentary, I was always kind of upset at articles like this that misled me for so long.
- acemarke 8y agoPlease see my other comments in this thread about our current work to refactor React-Redux to use new context. FWIW, it's not "just" about new context - there's a lot of other aspects we have to take into account, including trying to figure out how to best make React-Redux work with the upcoming "async rendering" capabilities of React, as well as the multitude of ways the community is using React-Redux beyond just the standard patterns.
- gwillz 8y agoYes, and I'm really excited to see it. Not to say I don't already use react-redux, it's simply a good academic process to write your own. It's good to know that everyone is together with bringing on async rendering. Thanks for your efforts!
- fiatjaf 8y agoMy rule of thumb: if you need Redux or the React Context API then your app is too big to be worth writing.