
Redux vs. The React Context API - wheresvic1
https://daveceddia.com/context-api-vs-redux/
======
jefflombardjr
React 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#...](https://facebook.github.io/flux/docs/in-depth-
overview.html#content)

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?la...](https://twitter.com/dan_abramov/status/964946781493780480?lang=en)

~~~
timdorr
We use the legacy Context API: [https://github.com/reduxjs/react-
redux/blob/47facdbcae2412d3...](https://github.com/reduxjs/react-
redux/blob/47facdbcae2412d37d72fa5c37cb4e0cd64a9b4a/src/components/connectAdvanced.js#L139-L146)

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
Very 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.

~~~
acemarke
Yep, and that was always the advice from the React team. "Don't use legacy
context directly in your apps. Libraries may need to use it. If you _need_ to
use it, wrap it up in a HOC or something so that you can update it in one
place later."

------
alangpierce
Redux 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.

~~~
WalterSear
Funny, 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.

~~~
52-6F-62
Have you tried MobX? I feel somewhat the same, and I’m that way MobX has been
a good in between for my work involving web interfaces. It’s been extremely
easy to implement into older projects using no globalized state as well.

~~~
joelhooks
We use MobX as a dependency injector, and it’s been great. Scales up very well
and is fairly simple to get people up to speed when they drop into our
project.

Redux was a “wtf” as it grew in our app and was a real struggle to back out
of.

------
talkingtab
My 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
I’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.

------
ncphillips
This 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
Yes, 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)

~~~
joelhooks
The egghead Redux series has been very popular and useful for users. We’d love
to talk about how we can compliment this documentation revamping with
updated/new free resources. joel@egghead.io

~~~
acemarke
Yep, it's highlighted in our README and "Learning Resources" docs pages, and
it's the first thing I recommend after the docs in my own "Suggested Resources
for Learning Redux" blog post (
[http://blog.isquaredsoftware.com/2017/12/blogged-answers-
lea...](http://blog.isquaredsoftware.com/2017/12/blogged-answers-learn-redux/)
).

Leave a comment in issue 2590, or DM me on Twitter or something - happy for
any assistance you can offer!

------
dmix
> 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.

~~~
stevehawk
Ya. 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.

~~~
dceddia
Thanks for the honest comments. What would you like to see in addition to what
it covers so far?

While I intentionally kept it focused on "pure React" because I felt that a
big part of the "React is hard" sentiment seems to come from how much _other
stuff_ gets lumped in with it (and then people feel compelled to learn it all
at once), I've been considering expanding it to include some other tangential
stuff e.g. API calls, basics of testing... any other ideas would be great to
hear!

~~~
stevehawk
The big hang up I remember having was the desire for a bit more into stubbing
out when and where AJAX belongs. I felt like I still had a gap between the
dummy application's data handling and how I'd be hitting my server side APIs
when I needed them.

I'm a mostly backend programmer and i remember when i was done with the book
thinking "ok i can shoe horn my ajax calls into this but I don't feel
confident this is how I'm supposed to." ultimately I got set straight on IRC
and discord.

I do enjoy your writing style and your blog posts though, and honestly did
find your book helpful.

------
jadbox
I 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.

~~~
solidr53
MST 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
Do you use it with React Native?

~~~
solidr53
Heck yes! [https://github.com/birkir/hekla](https://github.com/birkir/hekla)

------
k__
If 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
Context 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
I use constate which is very similar to Unstated:
[https://github.com/diegohaz/constate](https://github.com/diegohaz/constate)

------
MatthewPhillips
I'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?

~~~
alangpierce
It 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
That'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
Makes 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.

~~~
williamdclt
Yeah I've had the same kind of problem: 100% test coverage by unit testing but
I still had crashes because I wasn't testing integration.

I'd like to move to a page-based testing, where I mount the entire page and
interact with it, asserting what's going on visually and in the store

------
lewis500
This 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...

------
gwillz
It'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
Please 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
Yes, 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!

------
jinushaun
Redux 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.

------
crooked-v
Why not both? [https://github.com/icopp/react-redux-provider-
consumer](https://github.com/icopp/react-redux-provider-consumer)

~~~
acemarke
See 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
Something 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
Mmm... not sure I really see a difference between that and what `connect` does
right now. Can you clarify with a specific example?

~~~
crooked-v
Compare...

    
    
        // 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.

~~~
acemarke
So... 5 lines of code, vs 4 or 3?

Perhaps it's just that I'm very used to `connect` as the "standard" way of
doing things, or that I don't use TS myself, but I'm really not seeing that
much of a change in those examples (especially if you're importing pieces from
other files that already abstract some aspect of the process).

After we get done with version 6 (update to use new context), we are open to
ideas for new API approaches for a v7. If you've got specific suggestions,
please either file an issue, or wait for us to open up some discussions and
give us your thoughts then.

------
dmix
Is there something equivalent to the Context API in Vue.js?

~~~
philliphaydon
> 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.

------
sbr464

      // Note that it's named with UpperCase, not camelCase
    

Refers to Pascal case

------
beders
How do you test all this magic going?

------
fiatjaf
My rule of thumb: if you need Redux or the React Context API then your app is
too big to be worth writing.

