Unlock seamless workflows and faster delivery with our latest releases - Join the deep dive

Handling checkbox filters in a NextJS app with Groq queries and React state

25 replies
Last updated: Aug 10, 2022
I'm trying to create a checkbox filter in my NextJS app. How would I handle filtering out sanity documents that don't meet the checkbox requirements? (I would post code but I don't even know where to begin)
Aug 2, 2022, 11:27 AM
Once you have a boolean field in your schema, you can just use
foo == true
or
foo == false
in your Groq query. 🙂
Aug 2, 2022, 12:01 PM
hmm okay so for example if I have a query like
*[_type == "fruit"]{
Aug 2, 2022, 12:25 PM
hmm okay so for example if I have a query like
*[_type == "fruit"]{
  name,
  image
}
How would I dynamically change this with the checkbox? or would each checkbox call a new query?
Aug 2, 2022, 12:26 PM
I’m a little confused. What are you trying to do? 😅
Aug 2, 2022, 2:52 PM
My understanding was that your schema (
fruit
here) has a boolean field that you want to query. But I might have misunderstood you.
Aug 2, 2022, 2:53 PM
in next im using
getServerSideProps
to fetch data from sanity using a groq query of the above, but I want to be able to filter it after the initial fetch to only show specific documents that have been checked off
Aug 2, 2022, 3:12 PM
And it may be that I should be using a different method for fetching but there's other data I need from sanity on the page as well which is part of the getServerSideProps query
Aug 2, 2022, 3:13 PM
Hi Brian! If I’m understanding correctly, you can include the boolean in your projection and then handle the boolean when you map over your fruits. For example, if your
fruit
document has a boolean called
hide
, your query might look like:

*[_type == "fruit"]{
  name,
  image,
  hide
}
Then once
getServerSideProps
returns your array of `fruit`s, you might do:

return fruits.map(fruit => fruit.hide !== true ? fruit : null)

fruits
may need to be destructured, depending on your setup. You’ll also likely want to modify
fruit.hide !== true
to your liking—it’s worth noting that unless you’ve handled indeterminate booleans explicitly in your Studio (with validation or initial values),
true
and
false
aren’t the only options (i.e.,
fruit.hide !== true
would return both
false
and indeterminate values).
Aug 2, 2022, 7:19 PM
Thanks! I'm not sure I really understand how the checkbox filter on the front end will be able to do this, but I guess thats more of a matter of checkbox validation and handling state within next
Aug 2, 2022, 7:31 PM
Maybe I misunderstood. Is the boolean part of your schema, or is it more along the lines that you’ll have a bunch of checkboxes on your front end for different fruits and you want to only return the documents that have that fruit checked?
Aug 2, 2022, 7:34 PM
The later, I could add the boolean to my schema if needed but essentially I'm trying to have checkboxes on the front end that will be able to filter the list of fruit documents based on whether they are checked or not
Aug 2, 2022, 7:36 PM
And apologies for posting this in groq if it's not really a groq question. I wasn't sure if I should be writing a new query or what
Aug 2, 2022, 7:40 PM
Not to worry!
In that case, the boolean won’t go in your schema as I originally suggested as it doesn’t seem to be content but rather a means of filtering. If you’re looking for something like
this CodeSandbox demo , then hopefully that can help (it’s using class components but the fundamentals are similar even if you’re using hooks).
Aug 2, 2022, 7:53 PM
That looks like what I'm looking to do, thanks for the help!
Aug 2, 2022, 7:56 PM
One other quick question how would state in React translate to Next?ex.

state = {
    products: productsList,
    categories: {
      first: false,
      second: false,
      third: false,
      forth: false,
    }
  };
Aug 2, 2022, 8:25 PM
That example I provided uses class components, so it probably wasn’t the best example to send you (though it still works in React as well as Next.js). I’ve updated it to use hooks (i.e.,
useState
) here: https://codesandbox.io/s/react-checkboxes-filter-forked-4oz39s?file=/src/App.js
One change I made was to show nothing if no boxes are checked (the previous example showed everything). You can revert that by changing
null
to
products
on line 49 of App.js.
Aug 2, 2022, 10:09 PM
Thank you!!
Aug 3, 2022, 11:38 AM
When using this with sanity data, can I use the
_id
that sanity gives documents by default for the id that needs to be set to map things in
<li id={id}>
?
Aug 10, 2022, 8:49 PM
^^ this is in reference to inside the ProductList.js
Aug 10, 2022, 8:50 PM
Yes, as long as the
_id
will always be unique in your map, it’s the perfect candidate to use as the key in React.
Aug 10, 2022, 8:51 PM
So to do that I would just change the id to be
_id
like this?
const ProductList = (props) => {
  const { products } = props;

  const renderProducts = products?.map(({ _id, title, category }) => {
    return (
      <li key={_id}>
        <Product title={title} category={category} />
      </li>
    );
  });

  return <ul>{renderProducts}</ul>;
};

export default ProductList;

Aug 10, 2022, 9:02 PM
That looks correct.
Aug 10, 2022, 9:03 PM
hmm on the front end I'm getting a hydration err
Error: Text content does not match server-rendered HTML.
and in the console I'm getting

Warning: Each child in a list should have a unique "key" prop.
Check the top-level render call using <ul>. See <https://reactjs.org/link/warning-keys> for more information.
    at li
    at ProductList (webpack-internal:///./components/ProductList.js:14:13)
Aug 10, 2022, 9:05 PM
Does that error only happen after adding the key?
Aug 10, 2022, 9:06 PM
If I remove the key I get the same error
Aug 10, 2022, 9:07 PM

Sanity– build remarkable experiences at scale

Sanity is a modern headless CMS that treats content as data to power your digital business. Free to get started, and pay-as-you-go on all plans.

Was this answer helpful?