Transcript from the "Arguments: Context" Lesson
>> Scott Moss: All right let's get into the arguments a little more in detail. So we already talked about the root argument and how that gets passed. I talked about it a little bit as well, it's like how do you get these top-level resolvers? And by the way, when I say top-level resolvers I'm talking about resolvers that like, basically belong on query and mutations.
[00:00:20] If you have a field that's on a query or mutation, those are top level resolvers, that's at least what I call them. So how do you get root values for those? Only way to do that is you pass root value into your server at the start, and that depends on what server you're using.
[00:00:34] We using GraphQL-Yoga, they have an option there that says root value. You can put whatever you want there. But if you don't, it's just gonna be no. So that's gonna be the first argument. The second argument is always going to be the args. These args are what's gonna be passed in from the query, and that can be on any place.
[00:00:55] For instance, I can make this take args too. I can make any field take args, it doesn't matter. I can put args here if I wanted to. I don't know why your name would need a string or an ID, but yeah, I could do that, doesn't matter. And that's what args is gonna be.
[00:01:10] And that's always gonna be for that specific field, if that makes sense. Only for that field, not for the operation, only for that field. The second one is context and this one is pretty awesome. If you looked at these resolvers, you'll notice I'm using context everywhere. Context.models, context.models, this stuff is everywhere.
[00:01:30] So where is this coming from? Let's take a look. If you go into server, actually if you go into API index, there we go. You'll notice in here, this is where I'm kinda initializing the server, I have something called a context object. And basically, you can think of context as like dependency injection for your resolvers.
[00:01:56] That's the way I think of it. It took me a while to learn this pattern, but before when I would write my resolvers, if they needed access to the database or any model, I would just import them or require them at the top of the file, just like you would in any other thing, right?
[00:02:09] Like, of course. But what happens is when you do that, it's really hard to test your resolvers. So what you would instead is you would use context. So if you use react, it's basically like the same thing or if you use angular, it's like dependency injection. This is how you can inject like global things into your resolvers and then why you attach, you can change them, and you can share state across resolvers basically.
[00:02:30] Like how do I share a state across resolvers? This is where you would do it. So in our instance, it made sense for me to put all of our database models on the context, and then we'll talk about loaders later. Placing all that on the context allows us to always have access to those models and those shared state anywhere inside of our resolvers without having some external dependencies.
[00:02:54] So, we want to write tests, we can mock that out super easily just by overriding what context is. Any questions on context? They can be whatever you want. You can put literally whatever you want. So most people, they just put models. Loaders is another one. If you have third-party APIs, if you're doing something with the word stripe, you'd put all that on context.
[00:03:16] If you really wanted separation of concerns, and really good testable code, you would put it on the context. And I would say, try to avoid importing anything. Like, I think in this whole resolver file, I don't think I'm importing anything. I just put it all into context, which is so much easier to test.
[00:03:34] You will hit a brick wall if you don't do that, trust me. I'm still refactoring some of that in my code I type. So it sucks. [LAUGH] But yeah, context is just an object for that.