Skip to content

fraserxu/next-graphql-github-demo

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

9 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

init project.

yarn init -y

add dependencies.

yarn add yarn add apollo-client graphql next@latest react-apollo react-redux redux redux-thunk cowsay-browser

add pages/index.js.

import React from 'react'
import cowsay from 'cowsay-browser'

export default () => (
  <pre>{ cowsay.say({ text: 'hi next graphql github demo!' }) }</pre>
)

add npm run scripts to package.json.

"scripts": {
  "dev": "next",
  "build": "next build",
  "start": "next start"
}

start dev server

npm run dev

Connect redux and apollo-client to AppContainer

Create apollo-client instance with initClient.js

const client = new ApolloClient({
  ssrMode: !process.browser,
  headers,
  dataIdFromObject: result => result.id || null,
  networkInterface
})

Connect to Github Graphql api

const TOKEN = process.env.TOKEN

const networkInterface = createNetworkInterface({
  uri: 'https://api.github.com/graphql'
})

networkInterface.use([{
  applyMiddleware (req, next) {
    if (!req.options.headers) {
      req.options.headers = {}
    }

    // Send the login token in the Authorization header
    req.options.headers.authorization = `Bearer ${TOKEN}`
    next()
  }
}])

Create redux store with initStore.js

let reduxStore = null

export default (client, initialState) => {
  let store
  // only create store when it's not avaible in browser or on server side
  if (!process.browser || !reduxStore) {
    const middleware = createMiddleware(client.middleware())
    store = createStore(getReducer(client), initialState, middleware)
    if (!process.browser) {
      return store
    }
    reduxStore = store
  }

  return reduxStore
}

Hook up apollo-client and redux store into application with withData HOC

static async getInitialProps (ctx) {
  const headers = ctx.req ? ctx.req.headers : {}
  const client = initClient(headers)
  const store = initStore(client, client.initialState)

  const props = {
    url: { query: ctx.query, pathname: ctx.pathname },
    ...await (Component.getInitialProps ? Component.getInitialProps(ctx) : {})
  }

  if (!process.browser) {
    const app = (
      <ApolloProvider client={client} store={store}>
        <Component {...props} />
      </ApolloProvider>
    )
    await getDataFromTree(app)
  }

  const state = store.getState()
  return {
    initialState: {
      ...state,
      apollo: {
        data: state.apollo.data
      }
    },
    headers,
    ...props
  }
}

Querying data

const login = gql`
  query AppQuery {
    user (login: "fraserxu") {
      repositories(first: 100) {
        edges {
          node {
            name
          }
        }
      }
    }
  }

Select data from container

export default graphql(login, {
  props: ({ data }) => ({
    data
  })
})(repos)

Render data to page

const repos = (props) => {
  const { user: {
    repositories: {
      edges
    }
  } } = props.data

  return (
    <section>
      repos...
      <ul>
        {edges.map((edge, index) => (
          <li key={index}>{edge.node.name}</li>
        ))}
      </ul>
    </section>
  )
}

Releases

No releases published

Packages

No packages published