├── .gitignore ├── README.md ├── knexfile.js ├── now.json ├── package.json ├── pages ├── api │ ├── companies.js │ └── jobs.js ├── companies │ └── [id].js ├── index.js └── jobs │ └── [id].js ├── public ├── favicon.ico └── zeit.svg ├── src └── db.js └── yarn.lock /.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. 2 | 3 | # dependencies 4 | /node_modules 5 | /.pnp 6 | .pnp.js 7 | 8 | # testing 9 | /coverage 10 | 11 | # next.js 12 | /.next/ 13 | /out/ 14 | !public/ 15 | 16 | # production 17 | /build 18 | 19 | # misc 20 | .DS_Store 21 | .env* 22 | 23 | # debug 24 | npm-debug.log* 25 | yarn-debug.log* 26 | yarn-error.log* 27 | 28 | # Environment Variables 29 | .env 30 | .env.build 31 | 32 | .now -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Next.js Hooks Database Demo 2 | 3 | Video: https://youtu.be/QABkof8ygzI 4 | 5 | Fetch your props directly from the Database?!?! Adam Wathan showed a simple example of loading props directly from the database: https://twitter.com/adamwathan/status/1246144545361997829 6 | 7 | In this video we'll explore this hook, along with two others for building static pages. Next.js 9.3 came out with 3 new hooks that allow you to fetch data in different ways: 8 | 9 | - getServerSideProps: Fetch data server side 10 | - getStaticPaths: Fetch data to generate static pages 11 | - getStaticProps: Fetch data to build a static page 12 | 13 | ## Links 14 | 15 | - Source code: https://github.com/leighhalliday/nextjs-hooks-database 16 | - Deployed app: https://next-hooks-database.now.sh/ 17 | - Full Stack Radio episode about Next.js: http://www.fullstackradio.com/137 18 | - Release notes for Next.js 9.3: https://nextjs.org/blog/next-9-3 19 | - Learn JavaScript, React & more with Treehouse (affiliate link): https://treehouse.7eer.net/c/1214671/228915/3944 20 | -------------------------------------------------------------------------------- /knexfile.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | development: { 3 | client: "postgresql", 4 | connection: process.env.PG_CONNECTION_STRING, 5 | migrations: { 6 | tableName: "knex_migrations", 7 | }, 8 | }, 9 | 10 | production: { 11 | client: "postgresql", 12 | connection: process.env.PG_CONNECTION_STRING, 13 | migrations: { 14 | tableName: "knex_migrations", 15 | }, 16 | }, 17 | }; 18 | -------------------------------------------------------------------------------- /now.json: -------------------------------------------------------------------------------- 1 | { 2 | "env": { 3 | "PG_CONNECTION_HOOKS_DEMO": "@pg-connection-hooks-demo" 4 | }, 5 | "build": { 6 | "env": { 7 | "PG_CONNECTION_HOOKS_DEMO": "@pg-connection-hooks-demo" 8 | } 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "nextjs", 3 | "version": "0.1.0", 4 | "private": true, 5 | "scripts": { 6 | "dev": "next dev", 7 | "build": "next build", 8 | "start": "next start" 9 | }, 10 | "dependencies": { 11 | "death": "^1.1.0", 12 | "knex": "^0.20.15", 13 | "next": "^9.3.3", 14 | "pg": "^8.0.2", 15 | "react": "^16.13.0", 16 | "react-dom": "^16.13.0", 17 | "swr": "^0.2.0" 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /pages/api/companies.js: -------------------------------------------------------------------------------- 1 | import { db } from "../../src/db"; 2 | 3 | export default async (req, res) => { 4 | const companies = await db.select("*").from("companies").limit(50); 5 | 6 | res.statusCode = 200; 7 | res.setHeader("Content-Type", "application/json"); 8 | res.end(JSON.stringify(companies)); 9 | }; 10 | -------------------------------------------------------------------------------- /pages/api/jobs.js: -------------------------------------------------------------------------------- 1 | import { db } from "../../src/db"; 2 | 3 | export default async (req, res) => { 4 | let query = db.select("*").from("jobs"); 5 | if (req.query.company_id) { 6 | query = query.where({ company_id: req.query.company_id }); 7 | } 8 | const jobs = await query.limit(50); 9 | 10 | const companyIds = [...new Set(jobs.map(({ company_id }) => company_id))]; 11 | const companies = await db 12 | .select("*") 13 | .from("companies") 14 | .whereIn("id", companyIds); 15 | const companyDict = companies.reduce((acc, company) => { 16 | return { ...acc, [company.id]: company }; 17 | }, {}); 18 | 19 | const data = jobs.map((job) => { 20 | return { 21 | ...job, 22 | company: companyDict[job.company_id], 23 | }; 24 | }); 25 | 26 | res.statusCode = 200; 27 | res.setHeader("Content-Type", "application/json"); 28 | res.end(JSON.stringify(data)); 29 | }; 30 | -------------------------------------------------------------------------------- /pages/companies/[id].js: -------------------------------------------------------------------------------- 1 | import { useRouter } from "next/router"; 2 | import useSWR from "swr"; 3 | import { db } from "../../src/db"; 4 | 5 | export default function Company({ company }) { 6 | const router = useRouter(); 7 | 8 | if (router.isFallback) { 9 | return