1

I am needing to add bit of text in the sidebar of the following code. In each section, I need to have a count of the number of checkboxes selected. Is it at all possible to do this in a functional component as I have? Any examples that I have found so far are only for class components. I would like to keep it as a functional component if possible.

I have the code below, but here is a working version too:

https://codesandbox.io/s/react-playground-forked-jgmof?file=/index.js

import React, { useState } from "react";
import ReactDOM from "react-dom";
import styled from "styled-components";
import { categoryData } from "./data";

const Menu = (props) => {
  const [showPanel, togglePanel] = useState(false);

  return (
    <MenuWrapper>
      <p>Showing 20 results</p>

      <div className="button-wrapper">
        <p>Filter By</p>

        {categoryData.map((categorybutton, i) => (
          <div key={i}>
            <button key={i} onClick={() => togglePanel(!showPanel)}>
              {categorybutton.category}
            </button>
          </div>
        ))}

        <div>
          {showPanel && (
            <Sidebar>
              {categoryData.map((categorysection, i) => (
                <details className="dropdown-header">
                  <summary>{categorysection.category}</summary>

                  {categorysection.data.map((categorylabel, i) => (
                    <div key={i}>
                      <input
                        type="checkbox"
                        id="vehicle1"
                        name="vehicle1"
                        value="Bike"
                      />
                      <label for="vehicle1">{categorylabel.label}</label>
                    </div>
                  ))}
                </details>
              ))}
            </Sidebar>
          )}
        </div>

        <p>Toggle</p>
        <p>Clear all filters</p>
      </div>
    </MenuWrapper>
  );
};

const MenuWrapper = styled.div`
  width: 90vw;
  display: flex;
  justify-content: space-between;

  .button-wrapper {
    display: flex;
  }
`;

const Sidebar = styled.div`
  position: fixed;
  width: 200px;
  height: 100vh;
  background: white;
  top: 0;
  left: 0;
  z-index: 100000;
  text-align: left;

  .dropdown-header {
    background: #f7f7f7;
    margin: 20px;
  }
`;

ReactDOM.render(<Menu />, document.getElementById("container"));
export const categoryData = [
  {
    category: "user",
    data: [
      { checked: false, value: "Me", label: "Me" },
      { checked: false, value: "Kids", label: "Kids" },
      { checked: false, value: "Guestroom", label: "Guestroom" }
    ]
  },
  {
    category: "comfort",
    data: [
      { checked: false, value: "Ultra-Soft", label: "Ultra-Soft" },
      { checked: false, value: "Soft", label: "Soft" },
      { checked: false, value: "Medium", label: "Medium" },
      { checked: false, value: "Medium-Firm", label: "Medium-Firm" },
      { checked: false, value: "Firm", label: "Firm" },
      { checked: false, value: "Ultra-Firm", label: "Ultra-Firm" },
      { checked: false, value: "Unsure", label: "Unsure" }
    ]
  },
  {
    category: "type",
    data: [
      { checked: false, value: "Pillow Top", label: "Pillow Top" },
      { checked: false, value: "Open Coil", label: "Open Coil" },
      { checked: false, value: "Pocketed Coil", label: "Pocketed Coil" },
      { checked: false, value: "Quantum Coil", label: "Quantum Coil" },
      { checked: false, value: "Memory Foam", label: "Memory Foam" },
      { checked: false, value: "Latex", label: "Latex" },
      { checked: false, value: "Unsure", label: "Unsure" }
    ]
  },
  {
    category: "budget",
    data: [
      { checked: false, value: 500, label: "Under $500" },
      { checked: false, value: 1000, label: "$501 - $1000" },
      { checked: false, value: 1600, label: "1001 - $1600" },
      { checked: false, value: 2500, label: "$1601 - $2500" },
      { checked: false, value: 2501, label: "$2500 and up" },
      { checked: false, value: "Unsure", label: "Unsure" }
    ]
  }
];

0

1 Answer 1

2

If I understand correctly, you wan't to show the total number of selected items on each category.

It would be easy if we'll create a new component for the section that will have it's own state tracking its selected items.

Let's call it CategorySection. It would then have a selected state that will be an array (empty by default) of its selected items. To update our selected state, we have to fireup a function everytime any of the checkbox is changed — if the checkbox is checked, we add the current item to our selected state otherwise it will be removed.

Then to display the total selected items, we can simply count the length of our selected state.

function CategorySection({ categorysection }) {
  const [selected, setSelected] = useState([]);

  function onChange(event, item) {
    if (event.target.checked) {
      setSelected([...selected, item]);
    } else {
      setSelected((prev) =>
        prev.filter((currItem) => currItem.value !== item.value)
      );
    }
  }

  return (
    <details className="dropdown-header">
      <summary>
        {categorysection.category}{" "}
        {selected.length > 0 ? selected.length : null}
      </summary>

      {categorysection.data.map((categorylabel, i) => (
        <div key={i}>
          <input
            type="checkbox"
            id={categorylabel.value}
            name="vehicle1"
            value="Bike"
            onChange={(event) => onChange(event, categorylabel)}
          />
          <label for={categorylabel.value}>{categorylabel.label}</label>
        </div>
      ))}
    </details>
  );
}

Edit React PlayGround (forked)

PS: You should have a unique id for every checkbox on your page.

Sign up to request clarification or add additional context in comments.

4 Comments

Yes, that is perfect. Thank you so much!
Would it also be possible to get the {selected.length > 0 ? selected.length : null} from the summary into the buttons, so that the buttons could also show the count for their respective categories?
With the current code, I would do it like this. You might want to checkout Context.
No problem, glad I could help :)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.