Skip to content

Instantly share code, notes, and snippets.

@souporserious
Last active December 29, 2021 20:50
Show Gist options
  • Save souporserious/ece17001a4e2cbf87b3a7461788e3885 to your computer and use it in GitHub Desktop.
Save souporserious/ece17001a4e2cbf87b3a7461788e3885 to your computer and use it in GitHub Desktop.
Sync Leva controls with NextJS query params.
import { useControls } from 'leva'
import { useRouter } from 'next/router'
import * as queryString from 'query-string'
const roundValue = (value) => Math.round(value * 100) / 100
const parseValue = (value) => {
if (typeof value === 'number') {
return roundValue(value)
}
return value
}
const parseStringValue = (value) => {
if (value === 'true') {
return true
}
if (value === 'false') {
return false
}
return value
}
export function useParamControls<T>(options: T) {
const router = useRouter()
const augmentedOptions = Object.fromEntries(
Object.entries(options).map(([key, value]) => {
let nextValue = value.value === undefined ? value : value.value
if (nextValue !== undefined) {
const query = queryString.parse(router.asPath.split('?')[1])
const queryValue = query[key]
let firstPass = true
if (queryValue) {
if (typeof queryValue === 'number') {
nextValue = parseInt(queryValue, 10)
} else {
nextValue = queryValue
}
}
const handleChange = (value) => {
if (firstPass) {
firstPass = false
} else {
const currentQuery = queryString.parse(location.search)
const parsedValue = parseValue(value)
router.replace(
router.pathname,
`?${queryString.stringify({
...currentQuery,
[key]: parsedValue,
})}`,
{ shallow: true }
)
}
}
return [
key,
{
...value,
transient: false,
value: parseStringValue(nextValue),
onChange: handleChange,
},
]
}
return [key, value]
})
)
return useControls(() => augmentedOptions)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment