How to execute a GraphQL query from a Next.js app? - api

I have this Insomnia GraphQL command that I'm trying to put into a Next.js app. This is the actual API call that I've been running in Insomnia that I plan on moving into my Next.js app.
query getCharacters {
characters(page: 1) {
info {
count
}
results {
id
name
}
}
}
It's a super simple function... Here's what it looks like in Insomnia:
I found this example code for doing GraphQL function calls with Next.js: https://github.com/vercel/next.js/blob/canary/examples/api-routes-graphql. It requires typeDefs and resolvers to create a schema. I'm unfamiliar with this type of function call as I have always used simple rest APIs for previous apps.
I don't know what the typeDefs and resolvers are for https://rickandmortyapi.com/graphql 's getCharacters function?
Maybe I'm going about this incorrectly and I don't actually need to get getCharacter's typeDefs and resolvers. If I'm approaching this incorrectly, can someone show me how to execute this getCharacters function in a next.js graphql function properly?

Your app is going to act as a GraphQL client. TypeDefs and resolvers are written on the server. For example https://rickandmortyapi.com/graphql is the GraphQL server that you are trying to connect to and getCharacters is a particular query on that server.
There are many ways to execute a GraphQL query from next.js - these are well described in this article. I recommend using the apollo-client method rather than the lower level fetch or axios.

Related

Running method on every call using express-graphql

I'm using express-graqphl and was wondering if there is any concept of running a function before each graphql endpoint is executed? I'd like to have this for things like validating JWTs and other things. I realize we could use express for this, e.g.
app.use('/graphql`, doChecks);
but I'd like for the graphql handler to throw an error so it'll be inside the errors: [] list in the results giving the client a consistent experience with the api. Is there any direct support for this in the package?
The context function is executed before every request. If you're using Apollo v4+ then here are the docs
The context function is most often used to manage auth, including reading and validation of security tokens.

Prefetching API Data with Apollo for Nuxt.js SSR

I've got what is hopefully a very simple question about prefetching data from within an apollo/nuxt configuration.
I am requesting data from a GraphQL API and want to prefetch the data to use server-side rendering. Reading the docs it seems like I should simply be able to set prefetch: true on my apollo query but this is not working – it is always sending the request from the client side which is causing all kinds of issues.
Here is the code in my component:
apollo: {
concept: {
prefetch: true,
query: conceptStatements,
variables () {
return { id: this.$route.params.id }
}
}
}
I feel like it will have something to do with when this.$route.params.id is evaluated?
Ultimately I would like to create a Vuex store in the store/index.js which takes all of my apollo queries and renders the data in them accessible across the application but the documentation is very vague on how I might do this. Any help would be much appreciated!
Are you really sure your data is not prefetched?
Prefetch is for the first rendering (in SSR mode) ; Nuxt/Apollo call your graphql api, generate the page and send it to the browser. If you just navigate to your page from another route, nuxt call your api from the browser.
You can check this behavior in devtools/network, select xhr. Refresh your page, there is not xhr call. Go to another route and refresh your page, then navigate to your route where is your apollo query and you should see a xhr call to your graphql api.
Also, you can configure this behavior in your apollo config with fetchPolicy.
You don't need Vuex to store response of your apollo queries:
From vue-apollo doc:
When you perform GraphQL queries with Apollo, the results of API calls
will be stored in Apollo cache. Now imagine you also need to store
some kind of a local application state and make it available for
different components. Usually, in Vue application we can achieve this
with Vuex. But having both Apollo and Vuex will mean you store your
data in two different places so you have two sources of truth.
So, if your perform same query from different page or component, Apollo don't call your api each time, but retrieve data from the Apollo cache. Apollo is just magic!

Securing API keys in Nuxtjs

I've researched and found three different possibilities to solving my case: I'd like to make an async API call (using dotenv variables to store the credentials) and commit the returned data to Vuex on app init --keeping the creds secure.
Currently I'm attempting using serverMiddleware, but I'm having trouble accessing the context. Is this possible? Currently just getting a "store is not defined" error.
Also, after researching, I keep seeing that it's not a good idea to use regular middleware, as running any code on the client-side exposes the env variable... But I'm confused. Doesn't if (!process.client) { ... } take care of this? Or am I missing the bigger picture.
Additionally, if it does turn out to be okay to use middleware to secure the credentials, would using the separate-env-module be wise to make doubly sure that nothing gets leaked client-side?
Thanks, I'm looking forward to understanding this more thoroughly.
You can use serverMiddleware.
You can do it like this:
client -> call serverMiddleware -> servermiddleware calls API.
that way API key is not in client but remains on the server.
Example:
remote api is: https://maps.google.com/api/something
your api: https://awesome.herokuapp.com
since your own api has access to environment variables and you don't want the api key to be included in the generated client-side build, you create a serverMiddleware that will proxy the request for you.
So that in the end, your client will just make a call to https://awesome.herokuapp.com/api/maps, but that endpoint will just call https://maps.google.com/api/something?apikey=123456 and return the response back to you

How to update graphql endpoint (not using Graph.cool)

I spent some time working through the ReactQL starter kit and watched the intro video outlining how the kit is set up, but one area I am still confused on is where to put our graphql specific stuff if we don't use a Graph.cool endpoint.
Graph.cool seems great, but to get more experience with Graphql, I want to set up my own schema, queries, etc.
What is the best practice for handling our own graphql stuff? Do I place the:
app.get('/', {
graphiql: true
})
or Koa equivalent in the config/project.js APOLLO variable? I am more familiar with Express than Koa, but could also see it going in the entry/server.js file.
The GraphQL endpoint is set in config/project.js, under the APOLLO variable by default:
export const APOLLO = {
uri: 'https://api.graph.cool/simple/v1/cinomw2r1018601o42x5z69uc',
};
Change APOLLO.uri to point to another GraphQL server will update both the server and browser environments to use that new server.
If you want to create your own GraphQL server alongside the front-end web server that ReactQL starts by default, there's an example you can see here for wiring up your own schema and GraphQL endpoint:
https://github.com/reactql/examples/tree/master/graphql-server
(Usage instructions for example projects can be found here)

How do you pass data to react components from express or koa without renderToString?

I'm unable to use React's server side rendering due to my use of client side libraries such as reqwest. I would like to pass some data to my react components, however. Is there a way to do this?
The easiest way to do this is by having api-client.js and api.js. In your browserify/webpack config you set up a client side version. For browserify put this in your package.json (feel free to edit and add webpack).
"browser": {
"./path/to/api.js": "path/to/api-client.js"
}
The second option is better in my opinion, but more difficult to implement. You create an abstract representation of your API that works like this:
var comments = require('./api').get('comments');
comments.getById('7').then(function(comment){ ... });
comments.create({...}).then(...);
On the server api.js simply calls the correct functions, which all return promises. On the client it returns a promise, makes an ajax request to the server, which calls these functions, and sends back the response, and the api client resolves/rejects its promise.
This allows the api to automatically work, and allows you to do additional things like track unfulfilled promises, and pre-populate state on the client, etc. (see react-async for example).