How GraphQL Replaces Redux
hackernoon.com
hackernoon.com
This post is like all the others that tout, "moving from X language to Y saved us $3,000 per month on AWS" – it's usually not the transition from one tool to another, it's the fact that you rewrote your application with more knowledge and insight into the problem and have simply done a better job. Or in this case, a misuse of Redux led to a transition to GraphQL which painted Redux in a poor light.
There still isn't a compelling solution to problems like this... Apollo certainly isn't it. I want to feed GraphQL & REST into a central datastore in my application (be-it a Web/SPA/Browser app, or a local app) and abstract away the guts. A lot of devs are leaning on GraphQL for small experimental apps, fetching data in their components and violating every rule in the book on SRP and SOLID. It works for MVP's and hobby projects, but when you have a larger team, userbase, etc... the abstractions become critical.
We, as an ecosystem, need to focus more on those abstractions and not on the one-size-fits-all buzzword tooling. Server <> Datastore <> Application, not Server <> Application with the library of the week bolted in.
I'd suggest you give it a shot, it's super fun to work with and isn't going anywhere anytime soon.
> You can combine multiple data sources into a central datastore using GraphQL (REST APIs + DB queries etc.., that's one of the major benefits of it.
Would love to see the docs on this because I have yet to find it!
How GraphQL[1] Replaces[2] Redux
[1] Or any well designed back end API[2] For some narrow, often simple applications. And even in those cases it usually doesn't replace redux as much as it augments it.
So yes, you can replace Redux with something different. There are pros and cons to it, but it's not required or even fundamental to implementing GraphQL in a React app
Introducing state management doesn't come for free, of course. That is an extra layer of complexity that you have to reason and maintain. And if your app doesn't need any client side caching or you don't envision a need to have shared state between your components maybe you don't need to have something like Redux. But I feel like the use cases for those sort of apps tend to be pretty narrow.
edit: Another commenter mentioned a good point that gets to the heart of your question better than my rambling -- You are still managing state in your app - just with Apollo instead of Redux.
There are some new features in Apollo for handling client side state but I'm sticking to Redux for now (for client side state, I am using Apollo for some data fetching).
We control what is returned in data from our REST API by merely specifying the fields you want as a parameter. If there are use cases that would require multiple tables to be joined, those are created ahead of time as views with appropriate triggers for updates and then endpoints are created for accessing that view through RESTful methods. This has always worked just fine.
Not really. You can design specific REST endpoints to return the data in the format you want.
Wat.
Frontenders can write their frontend code in whatever they see fit. REST is a contract on data and format of the data between frontend and backend.
> Also, your backend guys are tied up constantly doing stupid endpoint changes, and both teams are wasting time messing around with extra effort to allow one side to be deployed before the other, instead of working on actual functionality work.
Well, if your teams are dysfunctional, then of course, that's what you will end up having.
Now tell me:
- what will you do when your glorious ad hoc GraphQL query ands up bringing the database to its knees?
- what will happen when your glorious GraphQL schema doesn't have all the data the frontend needs?
Oh, it’s a contract? Amazing, I guess that means you can just update the contract and nobody is stuck doing busywork anymore. Nope? I guess then either your frontenders need to learn your backend stack, lest they be stuck waiting for someone to do the busywork for them. I feel like I’m repeating myself, because I am. Please don’t quote out of context
> Now tell me: > - what will you do when your glorious ad hoc GraphQL query ands up bringing the database to its knees? > - what will happen when your glorious GraphQL schema doesn't have all the data the frontend needs?
Sound like interesting, challenging, and satisfying problems for the backenders to work on. Certainly more so than adding/removing fields from serialisers. These also seem like much more rare problems than the small data requirement changes that are the backbone of frontend work.
I’d rather work on speeding up the things that slow down development and deal with performance when it becomes a problem. I dunno, maybe our experience differ, and in you world your app is relatively static and performance is crucial, but the world I exist in involves stakeholders constantly wanting minor changes, performance has never been a problem, and development is constantly blocking because of frontend/backend blockers on our “rest” api and capacity on either side being wasted at various times because of that blocking.
Sure, sometime someone’s going to write a horrendous graphQL query where the answer is going to be “sorry, we can’t make that perfomant so we have to disallow it”, but that’s a: solvable and b: going to happen a lot less often than your frontend is going to need an extra field (or no longer need a field, but since nothing breaks these change requests rarely come through and your backend is eternally querying and sending unused data over the wire)
Why would frontenders need to learn the backend stack? Do you even know what REST is?
Riddle me this: what happens when frontend developers need data not exposed by the GraphQL schema? Do the need to learn the backend stuff as well? If not, why would they need that for REST?
> satisfying problems for the backenders to work on. Certainly more so than adding/removing fields from serialisers.
Because GraphQL automagically knows how serialize-deserialize any schema, riiiight.
> but the world I exist in involves stakeholders constantly wanting minor changes
So. How do you deal with those changes? Oh, let me see: you change schemas, you write new serializers/deserializers etc.
> development is constantly blocking because of frontend/backend blockers on our “rest” api and capacity on either side being wasted at various times because of that blocking.
For some reason you blame your failing processes on technology. Fix the process.
With REST you can have an N+1 query, but you're making multiple round trips from the client to the server. With GraphQL, you can also write an N+1 query, so you can shoot yourself in the foot either way.
I would probably use graphql-middleware to log the backend calls, or just look at my backend's log, identify the N+1 query and instrument data loader to batch it out. But of course you should load test your app before even shipping it so why would you have this problem unless you do not test?
- what will happen when your glorious GraphQL schema doesn't have all the data the frontend needs?
I can add the field without impacting existing clients that I have shipped. With REST, the old clients would also get the new field.
- if your teams are dysfunctional, then of course, that's what you will end up having.
The point is that your teams can function independently of each other, each focusing more effort on doing their own job & less time syncing with the other team.
With REST I can specifically optimise the calls because I know the contract and the possible incoming/outgoing requests.
> I can add the field without impacting existing clients that I have shipped. With REST, the old clients would also get the new field.
Why are so many people discussing REST in GraphQL threads so oblivious of what REST is?
One word: versioning
> The point is that your teams can function independently of each other, each focusing more effort on doing their own job & less time syncing with the other team.
Don't blame your failing processes on technology. There's nothing magical in GraphQL that makes it a magical thing making teams independent of each other. Tell me: what happens when frontend team requests data that's not exposed in the GraphQL schema?
Why are you discussing graphQL you're oblivious to the problem it solves. Graphql obviates the need to version, like with REST. Facebook had that problem with 30k react components, their processes are fine. My processes are fine too, you are obviously just biased against graphQL. You can specifically optimize a graphQL query by the way.
Versioning creates an explosion of REST end points in fast changing code bases. GraphQL solves that problem. If you don't have that problem then don't use it. You don't need to insult other people who are explaining the benefits it had in their project. That seems oddly defensive of REST, which is the de facto transport for a GraphQL query (they aren't even mutually exclusive). This comment thread is like arguing what is the better fruit apples or potato. And potatoes aren't a fruit
Ah. The old fallacy of "if it's good for Facebook, it's good for me".
> Versioning creates an explosion of REST end points in fast changing code bases. GraphQL solves that problem.
So. What happens when you change your GraphQL schema to an incompatible one? Just don't tell me a GraphQL schema is magically perfect from the start.
> That seems oddly defensive of REST, which is the de facto transport for a GraphQL query (they aren't even mutually exclusive).
It's not defensive. It's questions about the reality of things that every and all GraphQL proponents dismiss and brush over.
You can still technically version a graphQL API just the same as with REST. I haven't heard of anyone having to do this. In practice you add new fields and stop using old ones incrementally.
The biggest benefit is a front end developer can mock up a new UI without waiting on a new backend endpoint. You can a/b test many variations of your UI without a plethora of ad hoc end endpoints
It's on purpose. You can see it how Graphql is marketed in tech meet-ups. The proponents always argue against strawmen. I find it disgusting.
GraphQL is serializable & a graphQL query or mutation is conceptually the same as a standard FLUX action used by Redux.
The main difference is Redux intends to separate async logic & mutations, to make them easier to reason about in isolation. Apollo intends to remove the need to reason about async logic. In Apollo, you still have to deal with state mutations by refetching everything after any change, or writing verbose cache invalidation logic. So both Redux & Apollo make you reason about state mutations.
Apollo-link is like Redux middleware, it uses observables so its like redux-observable middleware.
If you treated Apollo like Redux, you'd have to fire a graphQL mutation as if it were a Redux action. In redux you can ignore an action. In Apollo, to ignore a mutation you would have to write custom apollo-link middleware to handle that action (mutation). As you can see redux & apollo solve overlapping but different problems.
If you are coalescing multiple API responses coming in over time, you may have a need for RxJS, not Redux. That is inherently a stream of events happening over time, so use a streams library (perhaps together with Redux).
[0] https://github.com/sysgears/apollo-universal-starter-kit
[1] https://github.com/apollographql/apollo-link-state
[2] https://github.com/adam-s/apollo-universal-starter-kit/commi...
[3] https://github.com/jaredpalmer/formik
[4] https://github.com/adam-s/apollo-universal-starter-kit/commi...
Which kind of makes sense, but I'm more biased towards thinking you'd almost always need some client-side work to reshape the response data because the front-end will always evolve at a different pace to the graphql endpoint, which ultimately has to be implemented by the server. Unless the entire team reaches this amazing point where the "graphql schema" and the abstractions in the app are just always in sync. Isn't it?
(Also, I love redux. Almost can't imagine using react without redux for any application. I started using react unreservedly, because redux. After disastrous attempts at flux. Redux is not going away I think.)
Maybe the lesson here isn't that GraphQL is a magic bullet, but that designing your API for your business needs solves a lot of frontend complexity (even if it's not pure "REST").
This is the single biggest advantage of GraphQL and AFAIK one of the main reasons for it's conception.
Not saying that being pure to rest ideology is a good thing. I think it’s a terrible fit for most applications more complex than a demo todo app
"The key abstraction of information in REST is a resource. Any information that can be named can be a resource: a document or image, a temporal service (e.g. "today's weather in Los Angeles"), a collection of other resources, a non-virtual object (e.g. a person), and so on."
By the way, REST is not an ideology, it's an architectural style. It defines a set of constraints, and specifies the advantages and disadvantages of applying each of them.
So.... That's why you decide to create ad-hoch APIs using GraphQL queries instead: "the client can control the shape of the data it needs"
It seems with an appropriate GraphQL query it would be possible to generate significant data retrieval server side.
In a nutshell, you can limit the depth to which a query will resolve in order to prevent abuse. You can also go much further and whitelist a specific set of queries (which comes with some additional bandwidth wins!) See https://dev-blog.apollodata.com/persisted-graphql-queries-wi...
For example, Found (https://github.com/4Catalyzer/found) uses Redux to keep route state. It's nice to use Redux in that context, because route state is global but also simple, not very hierarchical.
But for model state, Found integrates with Relay (https://github.com/4Catalyzer/found-relay/), because, as this article says, GraphQL reduces a lot of the REST/UI impedance.
I’ve personally tried it (with special attention on its capability to manage local state) and it did work out pretty well, with a lot of redux boilerplate code eliminated and a more effecient workflow, better yet, now you just need to learn one graphql syntax to rule them all.
https://dev-blog.apollodata.com/tutorial-graphql-subscriptio...
I've been using Apollo Client. When I add or delete data, I need to update the local store on Apollo.
How have you found your experience using the local store on Apollo versus Redux?
That's the true "replaces redux" statement.