Search code examples
gatsbynetlify

How can I perform a custom/dynamic sort in Gatsby based on a queryString param?


I've got a simple site that uses Gatsby w/ Netlify.

To "content" of the site is minimal at this point, so I keep it in a JSON file and generate pages / lists from that file.

The main purpose of the site is to show a list of files available for download. As the list got longer I implemented the following code to handle pagination, it works.

  const array_chunks = (array, chunk_size) =>
    Array(Math.ceil(array.length / chunk_size))
      .fill()
      .map((_, index) => index * chunk_size)
      .map(begin => array.slice(begin, begin + chunk_size))
  // const pages = array_chunks(edges.sort(customSort), pageSize)
  const pages = array_chunks(edges, pageSize)
  console.dir(pages)

  const handlePageChange = (event, data) => {
    setPage(data.activePage)
  }

  return (
    <div>
      <Table celled striped unstackable>
        <Table.Header>
          <Table.Row>
            <Table.HeaderCell singleLine>Report Name</Table.HeaderCell>
            <Table.HeaderCell singleLine>Released</Table.HeaderCell>
          </Table.Row>
        </Table.Header>
        <Table.Body>
          {pages[page - 1].map(({ node }) => {
            let countryName = node.country.toString().toLowerCase()
            return (
              <Table.Row key={node.id}>
                <Table.Cell>
                  <CountryIcon />
                  {node.name}&nbsp;
                  <DownloadLink url={node.reportUrl} external={node.external} />
                </Table.Cell>
                <Table.Cell>{node.date}</Table.Cell>
              </Table.Row>
            )
          })}
        </Table.Body>
      </Table>
      <Pagination
        boundaryRange={0}
        defaultActivePage={1}
        ellipsisItem={null}
        firstItem={null}
        lastItem={null}
        siblingRange={1}
        totalPages={pages.length}
        onPageChange={handlePageChange}
      />
    </div>
  )
}

Occasionally we direct people to the site and I want one of the reports to show up at the top of the list, instead of the default order. I implemented a custom sort function like this, and applied it to the pages variable as can be seen in the commented out line above.

  const customSort = (a, b) => {
    if (a.node.name.includes(reportName)) return -1
    return 0
  }

I've used .includes and startsWith methods because sometimes there are a couple reports, prefixed consistently that I want bubbled to the top. I can then visit the site like mysite.com/?reportName=myReportPrefix, and everything works. Once I deployed to Netlify, it all went sideways and I suspect it's because it generates the site statically, and that ruins my custom sort function - but it worked fine when developing locally because (presumably?) it's hot-reloading and the page has access to the queried data.

Is there any way to implement this functionality in production? Do I need to figure out how to have Gatsby generate a static page for each possible sort criteria? Any "right" way to do this?


Solution

  • Solved this.

    A few issues. 1, I had to coerce array.slice(begin, begin + chunk_size)) to numbers like array.slice(begin, Number(begin) + Number(chunk_size))) and I moved pages to a state variable and applied the sort in useEffect.