Skip to content

Commit

Permalink
Expose initUrqlClient in order to allow fetching data in SSR mode
Browse files Browse the repository at this point in the history
  • Loading branch information
Piotr Nalepa committed Sep 20, 2020
1 parent 8f3c757 commit 65a4fa9
Show file tree
Hide file tree
Showing 31 changed files with 5,138 additions and 0 deletions.
41 changes: 41 additions & 0 deletions packages/next-urql/examples/6-with-ssr-fetch/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
## `next-urql` - `with-ssr-fetch` Example

This example is a small reference of how to integrate `next-urql` with your NextJS SSR application exposing `initUrqlClient` and allowing to use it in `getServerSideProps` method. The project is a small Pokedex querying the excellent [Pokemon GraphQL API](https://github.com/lucasbento/graphql-pokemon).

### Installation

To get the example project running, follow these steps:

1. Install dependencies in the root of the `urql` monorepo:

```sh
# From urql repo root:
yarn
```

2. Build the `core` package in the `urql` monorepo:

```sh
# From urql repo root:
cd packages/core
yarn build
```

3. Build the `react-urql` package in the `urql` monorepo:

```sh
# From urql repo root:
cd packages/react-urql
yarn build
```

4. Navigate to this directory, install dependencies, and start the project:

```sh
# From urql repo root:
cd packages/next-urql/examples/6-with-ssr-fetch.js
yarn
yarn start
```

The example project should spin up at `http://localhost:3000`. `yarn start` will always run the build of the `next-urql` source, so you should see changes picked up once the dev server boots up. However, if you make changes to the `next-urql` source while the dev server is running, you'll need to run `yarn start` again to see those changes take effect.
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
import React from 'react';

import { Pokémon } from '../types'

const typesToIcon = new Map([
['Bug', '/types/[email protected]'],
['Dark', '/types/[email protected]'],
['Dragon', '/types/[email protected]'],
['Electric', '/types/[email protected]'],
['Fairy', '/types/[email protected]'],
['Fighting', '/types/[email protected]'],
['Fire', '/types/[email protected]'],
['Ghost', '/types/[email protected]'],
['Grass', '/types/[email protected]'],
['Ground', '/types/[email protected]'],
['Ice', '/types/[email protected]'],
['Normal', '/types/[email protected]'],
['Poison', '/types/[email protected]'],
['Psychic', '/types/[email protected]'],
['Rock', '/types/[email protected]'],
['Steel', '/types/[email protected]'],
['Water', '/types/[email protected]'],
]);

interface Props {
pokemons: Pokémon[];
}

const PokémonList: React.FC<Props> = ({ pokemons = [] }) => {
return (
<>
<div className="pokémon-list">
{pokemons.map(pokémon => (
<div key={pokémon.id}>
<img src={pokémon.image} className="pokémon-image" />
<div>
<h2>{pokémon.name}</h2>
<div className="pokémon-type-container">
{pokémon.types
.filter(type => typesToIcon.has(type))
.map(type => (
<div className="pokémon-type-container__type" key={type}>
<img
src={typesToIcon.get(type)}
className="pokémon-type-container__type-icon"
/>
<span className="pokémon-type-container__type-text">
{type}
</span>
</div>
))}
</div>
</div>
</div>
))}
</div>
<style>{`
* {
font-family: monospace;
}
.pokémon-list {
display: grid;
grid-template-columns: repeat(4, 1fr);
grid-template-rows: repeat(5, 1fr);
grid-gap: 1rem;
padding: 1rem;
}
.pokémon-image {
height: 15rem;
}
.pokémon-type-container,
.pokémon-type-container__type {
display: flex;
}
.pokémon-type-container__type {
margin-right: 0.5rem;
}
.pokémon-type-container__type-text {
background: #f1f8ff;
color: #0366d6;
padding: 0.5rem;
border-radius: 0.5rem;
}
.pokémon-type-container__type-icon {
height: 2rem;
}
`}</style>
</>
);
};

export default PokémonList;
2 changes: 2 additions & 0 deletions packages/next-urql/examples/6-with-ssr-fetch/next-env.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
/// <reference types="next" />
/// <reference types="next/types/global" />
8 changes: 8 additions & 0 deletions packages/next-urql/examples/6-with-ssr-fetch/next.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
const path = require('path');

module.exports = {
webpack(config) {
config.resolve.alias['next-urql'] = path.resolve(__dirname, '../../');
return config;
},
};
15 changes: 15 additions & 0 deletions packages/next-urql/examples/6-with-ssr-fetch/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
{
"name": "6-with-ssr-fetch",
"version": "0.1.0",
"private": true,
"scripts": {
"start": "next dev",
"prestart": "cd ../../ && yarn build && cd examples/6-with-ssr-fetch"
},
"dependencies": {
"graphql": "^14.5.8",
"graphql-tag": "^2.10.1",
"isomorphic-unfetch": "^3.0.0",
"next": "^9.2.0"
}
}
23 changes: 23 additions & 0 deletions packages/next-urql/examples/6-with-ssr-fetch/pages/_app.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import React from 'react';
import { withUrqlClient, NextUrqlAppContext } from 'next-urql';
import NextApp, { AppProps } from 'next/app';
import fetch from 'isomorphic-unfetch';

const App = ({ Component, pageProps }: AppProps) => {
return <Component {...pageProps} />;
};

// Implement getInitialProps if your Page components call getInitialProps themselves.
// https://nextjs.org/docs/advanced-features/custom-app
App.getInitialProps = async (ctx: NextUrqlAppContext) => {
const appProps = await NextApp.getInitialProps(ctx);

return {
...appProps,
};
};

export default withUrqlClient(() => ({ url: 'https://graphql-pokemon.now.sh', fetch }))(
// @ts-ignore
App
);
65 changes: 65 additions & 0 deletions packages/next-urql/examples/6-with-ssr-fetch/pages/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
import React from 'react';
import { NextPage, GetServerSidePropsResult } from 'next';
import { initUrqlClient, NextUrqlPageContext } from 'next-urql';
import Head from 'next/head';
import { Client } from 'urql';
import gql from 'graphql-tag';

import { Pokémon } from '../types';
import PokémonList from '../components/pokemon_list';

const queryPokémon = gql`
query pokemon($first: Int!) {
pokemons(first: $first) {
id
name
types
resistant
weaknesses
image
evolutions {
name
}
}
}
`;

interface InitialProps {
title: string;
data: Pokémon[]
}

const Home: NextPage<InitialProps> = ({ title, data }) => {
return (
<div>
<Head>
<title>Home</title>
<link rel="icon" href="/favicon.ico" />
</Head>
<h1>{title}</h1>
<PokémonList pokemons={data} />
</div>
);
};

export const getServerSideProps = async (ctx: NextUrqlPageContext): Promise<GetServerSidePropsResult<InitialProps>> => {
const graphQLClient = initUrqlClient({
url: 'https://graphql-pokemon.now.sh',
fetchOptions: {
headers: {
Authorization: `Bearer ${ctx?.req?.headers?.authorization ?? ''}`,
},
}
}, true) as Client;
const response = await graphQLClient.query(queryPokémon as unknown as string, { first: 20 }).toPromise();


return {
props: {
title: 'Pokédex',
data: response?.data?.pokemons
},
};
};

export default Home;
Binary file not shown.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
23 changes: 23 additions & 0 deletions packages/next-urql/examples/6-with-ssr-fetch/tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
{
"compilerOptions": {
"baseUrl": ".",
"paths": {
"next-urql": ["../../"]
},
"target": "es5",
"lib": ["dom", "dom.iterable", "esnext"],
"allowJs": true,
"skipLibCheck": true,
"strict": false,
"forceConsistentCasingInFileNames": true,
"noEmit": true,
"esModuleInterop": true,
"module": "esnext",
"moduleResolution": "node",
"resolveJsonModule": true,
"isolatedModules": true,
"jsx": "preserve"
},
"exclude": ["node_modules"],
"include": ["next-env.d.ts", "**/*.ts", "**/*.tsx"]
}
11 changes: 11 additions & 0 deletions packages/next-urql/examples/6-with-ssr-fetch/types/Pokemon.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
export interface Pokémon {
id: string;
name: string;
types: string[];
resistant: string[];
weaknesses: string[];
image: string;
evolutions: {
name: string;
};
}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export type { Pokémon } from './Pokemon';
Loading

0 comments on commit 65a4fa9

Please sign in to comment.