Skip to content

Instantly share code, notes, and snippets.

@bretmorris
Last active March 31, 2021 20:18
Show Gist options
  • Save bretmorris/eee518f96229cb3bf6f1910efa14bd84 to your computer and use it in GitHub Desktop.
Save bretmorris/eee518f96229cb3bf6f1910efa14bd84 to your computer and use it in GitHub Desktop.
using use-query to get calendar events by search query and updating URL query params
import { useState } from 'react'
import { useQuery } from 'lib/use-query'
const CalendarListing = () => {
const [loading, setLoading] = useState(true)
const [queryParams, setQueryParams] = useState({})
const [events, setEvents] = useState([])
const getEvents = async () => {
const urlParams = new URLSearchParams(window.location.search)
const params = {
search: urlParams.get('search'),
}
setQueryParams(params)
setLoading(true)
const data = await fetch(`/api/calendar?${serialize(params)}`)
setEvents(data)
setLoading(false)
}
const { updateUrl, serialize } = useQuery(getEvents)
const search = (e) => {
e.preventDefault()
const { value } = document.getElementById('events-search')
changeParam('search', value)
}
const changeParam = (key, value) => {
const newQueryParams = { ...queryParams }
newQueryParams[key] = value
setQueryParams(newQueryParams)
updateUrl('/calendar', newQueryParams)
}
return (
<>
<form onSubmit={search}>
<input
id="events-search"
placeholder="Search events"
defaultValue={queryParams.search}
/>
</form>
{!loading &&
events &&
events.length > 0 &&
events.map((event, i) => (
<div key={i}>
<div>Title: {event.title}</div>
<div>Description: {event.description}</div>
<div>Start: {event.start}</div>
<div>End: {event.end}</div>
</div>
))}
{!events || (events.length === 0 && !loading && <div>No events</div>)}
{loading && <div>loading...</div>}
</>
)
}
export default CalendarListing
import { useEffect } from 'react'
// cb: function to be called on component load and after URL changed
export const useQuery = (cb) => {
let event
useEffect(() => {
cb()
window.addEventListener('replaceState', cb)
return () => {
window.removeEventListener('replaceState', cb)
}
}, [])
// converts object into query param string
const serialize = (obj) => {
event = new Event('replaceState')
var str = []
for (var key in obj) {
// eslint-disable-next-line no-prototype-builtins
if (obj.hasOwnProperty(key)) {
if (obj[key] && obj[key] !== 'undefined') {
str.push(encodeURIComponent(key) + '=' + encodeURIComponent(obj[key]))
}
}
}
return str.join('&')
}
// updates the query params of the url
const updateUrl = (path, params) => {
const queryString = serialize(params)
window.history.replaceState(
{ path: `${path}?${queryString}` },
'',
`${path}?${queryString}`
)
// custom event to handle replaceState
window.dispatchEvent(event)
}
return {
updateUrl,
serialize,
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment