Thursday, 15 March, 2018 UTC


Summary

tl;dr; this function:
export const filterToQueryString = (filterObj, overrides) => { const copy = Object.assign(filterObj, overrides || {}) const searchParams = new URLSearchParams() Object.entries(copy).forEach(([key, value]) => { if (Array.isArray(value) && value.length) { value.forEach(v => searchParams.append(key, v)) } else if (value) { searchParams.set(key, value) } }) searchParams.sort() return searchParams.toString() } 
I have a React project that used to use query-string to serialize and deserialize objects between React state and URL query strings. Yesterday version 6.0.0 came out and now I'm getting this error during yarn run build:
 yarn run v1.5.1 $ react-scripts build Creating an optimized production build... Failed to compile. Failed to minify the code from this file: ./node_modules/query-string/index.js:8 Read more here: http://bit.ly/2tRViJ9 error An unexpected error occurred: "Command failed. Exit code: 1 
Perhaps this is the wake up call to switch to URLSearchParams (documentation here). Yes it is. Let's do it.
My use case is that I store a dictionary of filters in React this.state. The filter object is updated by submitting a form that looks like this:
Since the form inputs might be empty strings my filter dictionary in this.state might look like this:
{ user: '@mozilla.com', created_at: 'yesterday', size: '>= 1m, <300G', uploaded_at: '' } 
What I want that to become is: created_at=yesterday&size=>%3D+1m%2C+<300G&user=%40mozilla.com
So it's important to be able to skip falsy values (empty strings or possibly empty arrays).
Sometimes there are other key-values that needs to be added that isn't part of what the user chose. So it needs to be easy to squeeze in additional key-values. Here's the function:
export const filterToQueryString = (filterObj, overrides) => { const copy = Object.assign(filterObj, overrides || {}) const searchParams = new URLSearchParams() Object.entries(copy).forEach(([key, value]) => { if (Array.isArray(value) && value.length) { value.forEach(v => searchParams.append(key, v)) } else if (value) { searchParams.set(key, value) } }) searchParams.sort() return searchParams.toString() } 
I use it like this:
_fetchUploadsNewCountLoop = () => { const qs = filterToQueryString(this.state.filter, { created_at: '>' + this.state.latestUpload }) const url = '/api/uploads?' + qs ... fetch(...) }