5 ms·
GraphQL Deep Dive: The Cost of Flexibility
- spriggan3 11y agoSo basically you starts with React in the client. Of course React is new and shiny yet mandates that you do things differently when dealing with mutable data, so you need to adopt Redux. It creates a "impendance mismatch" with how REST API work, so you need to use GraphQL instead of REST endpoints, now you get that N+1 problem with RDBMS and GraphQL , so you need to add DataLoader on top ? what next ? having to ditch RDBMS and use facebook's solution whatever it is ? All I see is React generating an avalanche of issues and impedance mismatches that lead to having to change server-side code and potentially the datastore, just to fit a front-end js view library ? > For a simple RESTful API endpoint logic, it’s easy to analyze, detect, and solve N+1 issues by enhancing the constructed SQL queries. For GraphQL dynamically resolved fields, it’s not that simple. However, there is one possible solution that Facebook is pioneering for this problem: DataLoader.
- andybak 11y agoGraphQL solves a problem that you'll hit with any API client. It's nothing specific to React. REST APIs post a problem when you need to get complex nested representations (Do you do it in one request or many?). Any write operations that don't map easily to a single resource post a problem in terms of atomicity and ambiguity. I'm not sure how well GraphQL solves these but the problems aren't caused by React/Redux et al.
- steve_taylor 11y agoOr you can cut through all that bullshit and use React by itself which doesn't seem to present any major impedance mismatches. If you need to maintain global state (e.g. information about the currently logged in user), do that in the UI's root component. If you don't want to endlessly pass that global state down the component hierarchy via props, use contexts. Just keep your global state small and simple. What about actions? Just call methods on the root component that are specifically exposed to child components, perhaps also via contexts. There really is no need for Flux in most React web apps. It just adds confusion. Also, it's OK for components far down the hierarchy (i.e. leaves) to load their own data independent to their parent components. If you want clean separation of data and UI in that case, just use container components. https://medium.com/@learnreact/container-components-c0e67432e005 https://medium.com/@learnreact/container-components-c0e67432...
- spriggan3 11y agoMy point is this collection of libs and tools exist only to fix a flawed solution called React. If you need that much tooling to make React "just work" then React doesn't "just work", React is a trade off and just pushes complexity back to the server which goes against the philosophy of SPAs ( light weight servers , "fat" clients ). I mean why bother when you can just fetch HTML fragments from the server with AJAX directly ? That's basically the same thing as using GraphQL instead of a REST API.
- kccqzy 11y agoI would think otherwise: it's not that React itself is a flawed solution, but that it points out flaws in other parts of our stack, such as REST. I'm still writing REST APIs at work, but given a chance to start again I would have chosen something more GraphQL-like.
- davnicwil 11y agoThis is one of the most sensible comments about React I've ever read on HN. The now fairly extensive and ever-growing React ecosystem is really fantastic. But when React was first talked about and these libraries didn't exist yet, the phrase "it's just javascript" was often heard. That was a really powerful feature and philosophy that really went hand in hand with hacking really simple, small apps or components, and still remains a highly appropriate approach for those things. Somewhere along the line it seems to have stopped getting used, amongst the official and community blogposts about React (as an aside I'd love to see stats on the literal frequency of this phrase, over time) and basically in it's place a set of assumptions that you'll of course use a stack of popular ecosystem libraries to do everything for any size or class of app has appeared in its place. To me that's a real shame, and comments like this remind me that there are indeed still developers out there who are ready to push the philosophy of 'it's just javascript' and 'it's just data' when building React apps, when it's appropriate. Thanks!
- jondubois 11y agoI'm glad someone else mentioned the authorization problem. What if a user is allowed to access some of the resources declared in the GraphQL but not all of them... Do you block the request or do you allow it? Filtering out the non-accessible parts of the GraphQL seems like overkill. I work mostly with realtime WebSocket connections so my view is probably biased towards usage with realtime transports... But my favourite alternative approach to GraphQL is to just deal individual fields/properties of objects independently (for update operations). This avoids conflicts (like accidentally overwriting sibling properties with old values as part of an update operation). On create, you can create the whole object at once (with all properties) but for update, you only update each field independently. You end up with a realtime CRUD layer with field-level granularity. You do have to give up on transactional atomicity but I've found that the approach I've described above covers the vast majority of use cases. In those cases where you do need to update a whole object at once, you can setup a separate endpoint for that one - For me this usually only happens when I need to make a complex operation like 'Reset password' or 'Send email' which involves some specialized backend processing - Not something GraphQL would handle either.
- ericclemmons 11y agoIn my case, I let the query happen and throw at the part the user isn't allowed to see, which causes the entire entity to show as an error.
- _greim_ 11y ago> Do you block the request or do you allow it? Filtering out the non-accessible parts of the GraphQL seems like overkill. In Falcor (which is conceptually similar to GraphQL) you'd simply fulfill whichever parts of the request you can, and flag the unfulfilled parts as errors.