Creating & configuring the Next.js Application

To get started with a new Next.js app, create a new empty directory and change into the directory from the command line.

Next, run the following command to create a new package.json file:

npm init -y

In package.json, add the following scripts:

"scripts": {

"dev": "next",

"build": "next build",

"start": "next start"

}

Next, we’ll go ahead and install all of the dependencies we will need:

npm install --save next next-apollo-appsync react react-dom react-apollo aws-appsync graphql-tag

We can now create our folder structure. We need to create a pages folder with a file called index.js, and a withData.js component in the root directory.

touch withData.js

mkdir pages

touch pages/index.js

Finally, go ahead and move the AppSync.js file we downloaded from the AWS AppSync dashboard earlier & place it into the root directory of this project.

Next go into withData.js to configure the AWS AppSync client using the downloaded AppSync.js file:

Import our the withAppSyncData higher order component as well as our AppSync configuration Create a new config object setting the url, region and auth properties of the client Export the component

Now, we can update pages/index.js to receive and render data from the AppSync API:

The withData higher order component will wrap any component in which you would like to receive data and we can use it like we would on the client.

Running the app

Now, we should be able to run the app and see the todos on your screen and your data logged out to the console!

npm run dev

Mutations & subscriptions will all work the same as on the client. If you’re interested in some examples, keep reading!

Mutations + Optimistic Response

Let’s take a look at how to perform a mutation and add an optimistic response.

In our imports, we’ll import the compose HOC from react-apollo in addition to our previous imports:

import gql from 'graphql-tag'

import { graphql, compose } from 'react-apollo'

import withData from '../withData'

Next, we’ll define the mutation: const mutation = gql`

mutation createTodo($id: ID!, $name: String!, $completed: Boolean!) {

createTodo(input: {

name: $name,

completed: $completed

}) {

id

name

completed

}

}

`

In the AppWithTodos component definition, we’ll update it to use compose to compose both the existing GraphQL operation ( query ) as well as a new GraphQL operation, the mutation :

const AppWithTodos = compose(

graphql(mutation, {

props: props => ({

createTodo: todo => {

props.mutate({

variables: todo,

optimisticResponse: {

__typename: 'Mutation',

createTodo: { ...todo, __typename: 'Todo' }

},

update: (proxy, { data: { createTodo } }) => {

const data = proxy.readQuery({ query: query });

data.listTodos.items.unshift(createTodo);

proxy.writeQuery({ query: query, data });

}

})

}

})

}),

graphql(query, {

// this code stays the same

})

)(App)

Next, we’ll update the class to hold some state and add the addTodo class method we created above:

class App extends React.Component {

state = { todo: '' }

createTodo = () => {

const todo = {

name: this.state.todo,

completed: false

}

this.props.createTodo(todo)

this.setState({ todo: '' })

}

render() {

console.log('props: ', this.props)

return <div>

<p>Hello World</p>

<input

value={this.state.todo}

onChange={e => this.setState({ todo: e.target.value })}

/>

<button onClick={this.createTodo}>Create Todo</button>

{

this.props.todos.map((todo, index) => (

<p key={index}>{todo.name}</p>

))

}

</div>

}

}

The final code for creating a mutation with an optimistic response should look like this.

Subscriptions

To implement subscriptions, we need to do 3 things:

Define the subscription Create the subscription in the graphql HOC and pass it down as props to the component Initialize the subscription in the componentDidMount lifecycle method

Define the subscription:

const subscription = gql`

subscription onCreateTodo {

onCreateTodo {

id

name

completed

}

}

`

Next, we’ll create the subscription by updating the graphql HOC holding the query operation:

const AppWithTodos = compose(

graphql(mutation, {

// this code stays the same

}),

graphql(query, {

options: {

fetchPolicy: 'cache-and-network'

},

props: props => ({

todos: props.data.listTodos ? props.data.listTodos.items : [],

subscribeToNewTodos: params => {

props.data.subscribeToMore({

document: subscription,

updateQuery: (prev, { subscriptionData: { data : { onCreateTodo } } }) => {

return {

...prev,

listTodos: {

__typename: 'TodoConnection',

items: [onCreateTodo, ...prev.listTodos.items.filter(todo => todo.id !== onCreateTodo.id)]

}

}

}

})

}

})

})

)(App)

Finally, in componentDidMount , we’ll call the new subscribeToNewTodos function:

class App extends React.Component {

componentDidMount() {

this.props.subscribeToNewTodos()

}

// the rest of the class stays the same

}

The final code for creating a subscription should look like this.

To see a final example of this app, check out this repo.

To test everything out, run npm run dev to restart the app.