dogear

enter for all results · esc to close

Joseph Savona - Relay: An Application Framework For React

youtube.comvideo28 minby ReactEurope

Introduction to the Relay framework for React applications.

transcript

uh hi I'm Jose saona uh I work on the product infrastructure team at Facebook along with uh Lee and Spencer and many others from Facebook who are here today and I'm here today to talk about relay so relay is a framework that we developed at Facebook to manage uh data in client applications um yeah so I don't have speaker notes so I'm gonna do this live um so really in order to understand what relay is it's helpful to go back in time a year ago and think about how we were doing uh client side development on the web and you know also for Native um and you know wow I really don't have speaker notes this is gonna be great okay give me a moment give me a moment um let's speaker notes can wait I just need wise like sorry for the interruption sorry it's it's fine I'll just do it it's fine it's fine I'll just do it okay that's fine all right we're gonna do it it's all good um yeah I can't get to the display settings I don't know why mirroring there's no mirroring though Arrangements God damn it oh all right that's much better okay and the main display is the wrong one yeah okay that's much better all right now you can actually learn about relay instead of uh hearing me add Libs and stuff all right so now we're now we're all good all right so thank you for your patience sorry about that um so okay going back in time a year ago think about how we developed client side applications so obviously at Facebook developers have a choice of the Technologies they use but developers were choosing to use react and you know you're all here at react com you understand why right react makes it a lot easier to do client side development it's a simpler mental model we can think about components in isolation instead of having to reason about the entire system at this at once it's also a lot easier to think about views when we just return a rendering function right just declarative we just return what should happen and then react actually takes care of updating the Dom for us the top down data flow makes it really EAS easy to reason about the state of our application at any given time and flux compliments react Again by providing a consistent architecture for handling data change over time so you're all familiar with this uh you know with this architecture obviously Dan just talked about a lot of these ideas um great talk by the way Dan um but there's one piece that was missing right like react and flux are really great and they can and they continue to work really well for our developers but there is a missing piece and that missing piece is how to get data to and from the server and this doesn't seem like it would be a big deal but it actually turns out to be the source of significant friction for our developers so let's think about what was involved in this process so we're going to take this imaginary app that wouldn't it be cool if somebody made an app like this where I could post photos and my friends could comment on them um wait we did that um so you know we're react developers we're UI developers we see this and we're like I see components so let's just get them out of the way there's a feed right and it's the feed is going to represent the list of photos we'll have a media component uh that represents an individual photo with the header the image and the comments and then a comment component for each individual comment now obviously there's like you know a couple levels that you might choose to add like a comment list or you might choose to have a header but any we'll just focus on these three com these three components for now so now the question is you know this this you know this mockup looks pretty simple we've like we've got our components it should be really easy to build this application right I mean it's three components how hard could it be but you all know that the answer to that question is that it's actually really hard because the data has to come from somewhere and that's when you say oh what do I do now so there's a bunch of options right again we're developers we can solve this so I'll I kind of talk about a couple different options here and these might seem a a little bit extreme but they're kind of to illustrate the point so please don't react and say that I'm actually suggesting that any of these should be done exactly as is the first you might say well let's not read like Let's Not Duplicate our Logic on the server let's try to keep uh as much as possible each endpoint distinct so we might do something like this a feed endpoint that returns a list of photo IDs that should be rendered then the application can go and fetch information about each of those photos given the ID from from a photo endpoint of course the photo endpoint returns a list of comment IDs and so the application has to go and fetch the actual comment information okay so that's a lot of round trips that's really not maybe it'll work on desktop if you've got a really high bandwidth connection but on on on a mobile device with a slow Network it's really not going to be great so developer experience- wise okay it's easy enough we'll just hit in you know distinct endpoints but the user experience we get something like this we see a loading screen we see the first photo but the comments are still there Spinners Spinners lots of spinners and then you see here okay things start to break down because the third photo arrived before the second one did that's not wait did you would you expect that and then when the second photo comes in things are going to shift around on the screen so if I'm scrolling that's going to be kind of janky this is really not great right okay so that's not so cool let's try something else we'll just do like the total opposite we'll have one custom point that returns all the data we need for the entire application like it couldn't be any simpler right feed with photos and comments we're done go home like excellent right just ship it except you get this loading loading still loading oh look it's an app and the user's already gone um so clearly this is again not probably a reasonable approach in the end we probably all do something like this multiple custom endpoints and the way that we might do that for this application would be let's say a feed again that feed endpoint but we'll modify it this time and the feed will return all of the information for the media component so the Header information the photo as well as the comments and the author information and we can specify exactly how many photos we want to fetch but in order not to wait for all three we'll make separate fetches for the first item the second item the third item now we've got a really great user experience the first photo loads in the second photo loads in the third photo loads in and the user can just keep on scrolling through all right so we've kind of made a bit of a trade-off right we've got some duplication of you know possibly some duplication of our server logic because we're fetching the comments and the photos all in one end point we might need to fetch that information somewhere else but the user experience is pretty good but we all know we're not done yeah so there's edge cases uh as with everything we actually got to coordinate the requests we've got to write imperative logic that that makes sure that we fetch these things these end points in the correct order so regardless of which approach we've chosen whether it's the initial approach with reusable endpoints or one custom endpoint or multiple custom endpoints we have to write logic to manage that data fetching and think about how our local state is changing over time so local state changing over time we've seen that before right in the Dom with vents so this should start to feel familiar but there actually there's even more edge cases to consider right we don't want the third photo to load before the second one that's going to be hard to do but we'll figure out some way to do that um what if a new photo is taken so I load photos one two and three then I go to scroll but there's a new photo at the top so now one is at two two is at three oops sorry everyone sorry I'm Italian I talk with my hands um three becomes four and now when I scroll the third photo is at four and I see the same photo twice in a row so clearly pagination is not going to be as simple as just fetching another item there's actually a lot of logic that's going to have to go into it then you get into things like the Facebook news feed where it's algorithmic ranking and things can jump around in the feed and things get even more complicated and not to mention error handling retries timeouts all that stuff okay all right but we're like a month later and this the simple app is like maybe kind of done but things don't stay the same right we actually develop our apps and move on so this is an an uh a simple example of the comment component it's kind of starting at the the the simplest case and it's really simple right just the author's name and the text of the comment Prett easy now a designer might come along and say we want to show the photo of the of the author right just like see if that increases engagement see if people like you know enjoy the app more now again we're all react developers right so we see this and we think okay easy we'll just add an image and it really is just that easy to make the change or is it that information has to come from somewhere as we all know so you know here's our app here's our endpoint I'm just going to highlight the particular parts of the application that are going to be affected by this small change I'll just highlight only those parts in red yeah so it's really not that simple right because the media component gives data to the comment component and the feed gives passes data to the media uh the the media component and of course the endpoint fetches the data that goes into all this right so our simple simple uh change has turned into this um and what this means is you know that common component might be used in other places in the app there might be other endpoints that fetch data for it and so this one change requires a Cascade of uh changes throughout our application so if you're a new developer coming into this and you get a task that says add this you know add this photo you might think it starts off really easily but then that new developer has to figure out pretty much the entire system in order to make this one change so this really doesn't scale yeah but of course apps wouldn't be very interesting if we couldn't write data to them right obviously we've got to actually put some data into the system and wres are even more complicated than reads so there's a lot of different cases that can happen here if the user posts two comments in quick succession what happens if one of them gets what if it happens if the second one arrives at the server first right or if the responses arrive back from the server out of order how do we ensure that those comments are actually visible to the user in the correct order what happens if the user posts two comments but the first one fails for some reason just the network request doesn't go through don't even like not even getting into like authentication auth uh authorization all those things so we're going to handle those cases too what if the server response just simply takes a really long time how do we let the user know that that request is still pending and it hasn't just simply failed how do we show pending comments to the user so if I type something in it hit enter do we show the user that it's pending or do we just show nothing at all what if someone else comments on that same photo while I'm commenting on it I I write a comment you write a comment I write another comment how do we make sure those comments appear to the user in the correct order to both users in particular there's a lot of challenges to getting this right okay so this is insane developers were spending a lot lot of time rewriting all of these things these complex pieces of logic that had to be right or else the application would break it was really easy to miss an to you know to miss an edge case to forget to add some data to one particular endpoint and now have used somewhere as breaking and of course as I mentioned for new developers it's really hard to jump into the system and begin making changes being productive and having the confidence that the application is still going to work so this is why we built relay to make it easier for product developers to focus on products and not on these repetitive error prone pieces of logic and the first uh the first Insight Lee already mentioned in his talk on graphql but the key is that what we're doing here all of these approaches that we've discussed they couple the server endpoints to our render logic right so this fragile coupling means it's a lot easier to break our application the solution is pretty clear clients know exactly what data they need it's implicit in the render function when I say this. props author. photo I know I need that information the client knows what it needs so we just have to build a system that allows the client to express that and to fetch the and to drive the data fetching process but we already have this great unit of encapsulation the react component right we've all seen how powerful these declarative components are for handling views and the solution was to add a declarative uh description of the components needs inside the the component and we use obviously graphql to do this so we talked about this before let's look at how this actually works in in code so we'll start at the bottom of the application with the simplest component the comment now Lee already gave a demonstration of graphql so I'm just not going to touch on that too much but I'll just show an example of a graphql query so we've all seen we wanted the the comic component accesses the text of the comment and the author's name and photo and so the graph Co query expresses that exact structure and i' I've shown a sample response below again just plain JavaScript exactly matching that shape so now let's consider how we would actually implement this in relay so you can see at the top of of this file is the comment component that we already wrote before I've collapsed it because it doesn't have to change it stays exactly the same as it was instead we're instead of actually returning that to the application and directly using the comment with relay we'll create a container for that comment component and these containers are just basically higher order components they're regular react components that you don't have to know how they work inside they do the complex work for you and give your regular comment component props that are just plain objects plain arrays plain JavaScript objects no new API to learn you just get the same props you had before really just make sure the data is available for you so remember our comment component accessed this. crops. comment and so here we're defining queries. comment so the results of this graph whe query will be provided to the comment component as props do comment so it's exactly one toone correspondence between the props that we access in our component and the queries that we Define here so if you're not familiar with higher order components and or containers kind of two names for the same thing and the way it works is our regular comment component expects to receive some props but that would require us to actually fetch the data and make that and provide those props to the component so instead we can wrap that this relay container wraps that component and it says regular react component is it receives props for example a comment ID and it will go and fetch the data for that uh for that comment and take the results of that query and make it available to our comment component so if you're more mathematically minded you might choose to think of it as functions you know if you're a functional programmer what uh you know as Dan talked about there's a lot of a lot to that we can all learn from functional programming so our regular components really just a a function over the props and with relay we're just extending that and we're kind of annotating those props and kind of adding extra value to them taking the comment that you wanted to reference and returning the specific data for it so we've talked about so far how to handle a single a single component but of course our applications are built of multiple layers of components for example the media component composes comments right so here's a really really B basic version of the media component and we could all argue about my style of writing react components I would probably rewrite this one if I had to um but it'll it'll do for the for the sake of presentation so we're looking at the media. comment property and for each comment uh this component will return a comment item for that comment okay so again what we're doing here is composition and relay and graphql fully support a composition of queries and components as well so the way that would work in relay is again collapsing that media component basically stays the same and wrapping it in a new container again the the component accessed this. props do queries and so we'll provide uh sorry yeah props media and so here we're defining queries. media and for whatever media item we're looking at uh this component is going to fetch the first 10 comments and remember this is graphql so connections are edges there might be information about the relationship and so we actually have to look at the edge and look at the note at the at the other end of it and for each comment uh this component will fetch whatever requ whatever information is required by the comment component so there's really interesting property here before we saw that changing the comment component required us to change every part of our application with relay we don't have to do that the the component drives its own data fetching so a change to comment component won't require any changes to Media at all adding a new property we refresh the view and the new query that's composed will contain all all the information required by the comment so we can quickly make changes adding a property to our query adding a property to our view and all the information would just simply be there now you may have noticed also that I didn't add any logic to handle the case for data that's not already available right their components just sort of assume that the prop is somehow there and that's an important design decision in relay developers shouldn't have to worry about complex logic to handle what data is available what data isn't available by default we just want all of our data to be available when we render so really maintains that invariant it's going to fetch all of our required Data before ever rendering our components so we just access the data it's that's it to see how that works in practice we'll take a single component but you can imagine this is the top level component and of course it might compose many other components as well so really extract that component statically without ever having to render the component sends it to the server gets the response back and then can provide props to each of the views now the props that are provided to each view are only the exact information that's requested by each component so if you have two components that are both looking at the same comment and they ask for different sets of data they'll each only see the part they specifically asked for so you can't have some other part of your application change and break a different view each component is completely isolated but you know we talked about the whole if you fetch everything in one custom endpoint this looks a lot like the one custom endpoint solution right and we saw the problem was a really long loading spinner which we don't want so relay wouldn't really be useful if it didn't allow us to specify that not all of our dat is actually required up front but of course we still want to take advantage of efficient networking as much as possible we don't really want to try to make too many round trips if we can avoid it but we do need to kind of at some point uh delay loading so I've refactored the media component I've just put all those comments inside of a comment list component we'll just pass media. comments to it this makes it a bit easier to think about how instead of having to worry about uh the loop in just here it just kind of cleans up the code now with a normal system we would have to imperatively specify that the actual comments should be fetched separately and we don't need them right away right and to if we did that our component would have to handle the case for what if the comments aren't available what if we haven't f that yet so here we'll add an if an if statement if the med if the media. comments is fetched if it's available we'll render the comment list if not we'll render a spinner simple right again we don't have to actually think about what's happening all the asynchronous stuff that's happening we just think about given the data we have right now what's been fetched what do we render really easy to think about now all we have to do is tell relay which information is actually required and which information can be delayed and put off until Fetch and fetched later and we can do that with a simple annotation defer again we're not actually implementing the the custom logic to make this happen that really handles all of that for us we just tell relay this is a description of what we need and we're also annotating it with what is the priority of that information and defers says this isn't required so now when we render this component we see an initial loading spinner this is handled by relay when the information the required information is available relay will render our component but of course the comments aren't available yet so we see a spinner and then eventually when that deferred data becomes available relay will update our component and show that information so you know relay or any kind of data fetching framework wouldn't be useful if it didn't support rights uh my colleague Lany Kul gave a great talk at Json this year about how relay handles uh handles rights so if you're really interested in this topic I would encourage you to go look up that talk I'm just going to briefly touch on how rights are handled in relay today so again Rel was designed from the start for with a consistent architecture it's based on the flux model for handling wrs and reads wrs work where an action comes in from somewhere else in the system typically in response to user interaction that's sent to relay relay passes that information up to the server it actually does a lot of things here it ensures that as the after the right we're going to have all the information that possibly could have changed as a result of it but it's not going to over Fetch and fetch anything we don't care about so relay does a lot of work behind the scenes to ensure that we update our local view of the world but without having to fetch lots of extra information that the user doesn't care about as a result of fetching that information really updates its local store and provides updated props to components now obviously graphql pretty much implies it's a graph right our data is actually a graph there are cylic references so for example I might post a story like it and also like one of the comments I might write a comment on it so if you look at the actual data for that there's a lot of different paths that lead back to the same object as you can see here but our component Tre when we render our component Tre has you know three different instances of media we've got a comment over there the question is how do we actually update this tree given that something in the graph changed how do we know what changed with flux the developer has to manually specify which uh which components are listening to what data and manage that subscription subscribe when the component loads unsubscribe when the component is unmounted relay automates all of that for developers and relay knows exactly what data is is actually being referenced by each component so when a change occurs either we've fetched new information or a mutation action happens Relay can automatically update only the components that are actually affected without the user having to do anything and as you can see media updated but comment didn't if the if the information if the change does doesn't affect the comment component relay implements should component update by default and knows whether that component actually needs to update itself or not and so Relay can make uh changes really efficient so what is relay there's a lot of different pieces right there's data collocation we're using graphql I find it really helpful to to think about relay in terms of what developers had to think about before and what they think about when they're using relay what you had to think about before was how to do a lot of things how to actually fetch the data how to coordinate reads and writes right we saw that like that coordination is actually quite complex how to handle retries errors failures keeping a local cach of data in sync with a server right cash invalidation is as we all know a pretty hard problem and so once you get all of that in your head you can actually then get back to focusing on your app right but like we're here because we like building things we're UI developers the reason we're using react is that we want to build products and relay lets us do that relay says we specify what data to fetch and what order to fetch it in not how to actually go about implementing all that fetching it means that product developers are able to focus on their products and not on repeating all of that error prone logic in particular a lot of the the complexity in data fetching comes from the fact that ultimately it's an asynchronous problem client Network server there's simply no way to get around the fact that the problem is asynchronous UI development is async and that's all there is to it and there are a lot of great AP for working with asynchronicity right you can use calls you can use promises observables are really great and actually we use all of these things inside of relay we use callbacks we use promises and we use observables in certain cases the key is we don't expose those to the user and the reason is that while they are composable we can compose promises we can compose observables they still require the developer to think about the current state of their application so these are really great apis callbacks promises observables they're really great apis and they do make synchronous programming simpler but with relay and the declarative component based architecture we can actually eliminate a lot of those concerns the same way react eliminated the problem of managing state in the Dom really does the same thing for data fetching so this in a nutshell is relay it's working really well for us for managing data in really complex applications and as I mentioned it allows product developers to focus on their product and this is not just you know hypothetical we're using this in production apps Rel was developed from the start alongside products to solve the hardest problems that those products we facing and make them easy so you know we can't we can't make hard problems disappear but we can make hard problems go away and we can make the common case really simple so relay was designed and built for the web but it actually turned out to be so powerful on the web that we began using it for all of our data fetching inside react native so pretty much all of our react native apps use relay to the point where I think there might be some developers who think that they're the same thing although obviously with talks like this hopefully that'll go away again just like react relay provides a consistent development experience across platforms and a couple highlights we're using relay in the Standalone groups app for Facebook as well as the Standalone ads manager app all the data fetching is powered by relay so you know we were using relay internally it's been really successful for us we're continuing to use it in more and more products um and you know it doesn't solve all the problems right there's still some things that we're exploring but it does work really really well and we're looking forward to collaborating with the community on this obviously we've gotten asked by a lot of people we're planning to release relay open source in August and we really look forward to collaborating with all of you and to get your feedback as well so thank you and uh please ask questions later thanks thank you uh I think I'm out of time so uh just please find me afterwards I'll be around and ask questions thank you so much [Applause]

from
GraphQL, Relay
added
2026-10-10
likes
0

similar

  1. F8 2015 - React Native & Relay: Bringing Modern Web Techniques to Mobile youtube.com

    Presentation on React Native and Relay integration.

  2. Relay: Seamless Syncing For React slideshare.net
  3. react-native-relay github.com
  4. Relay - Daniel Dembach - Hamburg React.js Meetup youtube.com
  5. Introducing Relay and GraphQL legacy.reactjs.org

    Original announcement introducing Relay and GraphQL.

  6. GraphQL and Relay on Rails — First relay powered react component medium.com

GraphQL › Videos: “Introduction to the Relay framework for React applications.”

Relay › Overviews: “Conceptual overview of Relay from the Facebook team.”