Created
June 8, 2023 15:56
-
-
Save squashfold/6c6cf82db8802d424f711c6356eae121 to your computer and use it in GitHub Desktop.
Caching and Fetching posts in NextJS
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import Head from 'next/head'; | |
import { useCallback, useRef, useState, useEffect } from 'react' | |
import type Post from '../../interfaces/post' | |
import PostPreview from '../../components/post-preview' | |
export default function Home() { | |
const searchRef = useRef<HTMLInputElement>(null) | |
const defaultPosts = require('../../cache/data/posts').data; | |
const [query, setQuery] = useState('') | |
const [results, setResults] = useState<any[]>(defaultPosts) | |
const searchEndpoint = (query: string) => `/api/search?query=${query}` | |
const getResults = (query: string) => { | |
if (query.length) { | |
fetch(searchEndpoint(query)) | |
.then(res => res.json()) | |
.then(res => { | |
setResults(res.results.map((element) => element.item)) // Fuzzy search returns our results in a different format | |
}) | |
.catch(error => { | |
console.error('Error fetching search results:', error) | |
setResults([]) | |
}) | |
} else { | |
setResults(defaultPosts) | |
} | |
}; | |
const onChange = useCallback((event) => { | |
const query = event.target.value; | |
setQuery(query) | |
}, [query]) | |
useEffect(() => { | |
getResults(query); | |
}, [query]); | |
return ( | |
<> | |
<Head> | |
<title>{`Search`}</title> | |
</Head> | |
<div className={`container mx-auto px-5`}> | |
<h1 className={`text-5xl md:text-8xl font-bold tracking-tighter leading-tight md:pr-8`}>Search Articles</h1> | |
<div ref={searchRef} className={`mb-4`}> | |
<div> | |
<label htmlFor="searchInput" className={`mr-4`}>Filter:</label> | |
<input | |
className={`p-2 border-solid border-2 border-black`} | |
onChange={onChange} | |
placeholder='Search posts' | |
type='text' | |
value={query} | |
id="searchInput" | |
/> | |
</div> | |
</div> | |
<div className={`grid grid-cols-3 gap-4`}> | |
{results.map((post: Post, index) => ( | |
<PostPreview | |
key={post.slug} | |
title={post.title} | |
coverImage={post.coverImage} | |
date={post.date} | |
author={post.author} | |
slug={post.slug} | |
excerpt={post.excerpt} | |
/> | |
))} | |
</div> | |
</div> | |
</> | |
) | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
const path = require('path') | |
const fs = require('fs') | |
const greyMatter = require('gray-matter') | |
function getPostData() { | |
const postsDirectory = path.join(process.cwd(), '_posts') | |
const fileNames = fs.readdirSync(postsDirectory) | |
const posts = fileNames.map((fileName) => { | |
const postId = fileName.replace(/\.md$/, '') | |
const fullPath = path.join(postsDirectory, fileName) | |
const postData = fs.readFileSync(fullPath, 'utf8') | |
const result = greyMatter(postData) | |
return { | |
postId, | |
slug: postId, | |
title: result.data.title, | |
coverImage: result.data.coverImage, | |
excerpt: result.data.excerpt, | |
date: result.data.date, | |
author: result.data.author | |
} | |
}) | |
const postsData = `export const data = ${JSON.stringify(posts)}` | |
return postsData | |
} | |
try { | |
fs.readdirSync('cache') | |
} catch (e) { | |
fs.mkdirSync('cache') | |
} | |
fs.mkdir(path.join(__dirname, 'data'), | |
{ recursive: true }, (error) => { | |
if (error) { | |
return console.error(error) | |
} | |
console.log('Directory created successfully!') | |
fs.writeFile(`${path.join(__dirname, 'data')}/posts.js`, getPostData(), function (error) { | |
if (error) { | |
return console.log(error) | |
} | |
console.log(`Posts cached!`) | |
}) | |
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import type { NextApiRequest, NextApiResponse } from 'next' | |
import type Post from '../../interfaces/post' | |
import Fuse from 'fuse.js' | |
const posts = require('../../cache/data/posts').data | |
export default (req: NextApiRequest, res: NextApiResponse) => { | |
const fuse = new Fuse(posts, {keys: ['title', 'excerpt']}) | |
const query = req.query.query ? req.query.query.toString().toLowerCase() : '' | |
const results: Post[] = query.length ? fuse.search(query) : posts | |
res.statusCode = 200 | |
res.setHeader('Content-Type', 'application/json') | |
res.end(JSON.stringify({ results })) | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment