Handle multiple checkbox components in React

Viewed 350

I´m having issues with creating my checkbox component(s). Since I´m mapping over an object´s entries, where the keys are the sectiontitles and the values are arrays, filled with the checkable features.

I´m also using tailwind. I will let the code speek for itself I think :D

Checkboxes

Object structure, which im passing as a prop, down to the checkboxes component:

const features = {
  Features: [
    'Mintable',
    'Burnable',
    'Pausable',
    'Permit',
    'Votes',
    'Flash Minting',
    'Snapchots'
  ],
  'Access Control': ['Ownable', 'Roles'],
  Upgradeability: ['Transparent', 'UUPS']
}; 

Checkboxes component, which renders the checkbox component multiple times by mapping over the object (Ik the id is missing, but I dont know how to control the ID´s:

import React from 'react';
import { connect, useDispatch } from 'react-redux';

import Checkbox from '../../layout-blueprints/Checkbox';

import { featureCheckboxClick } from './Redux/actions';

const FeaturesComponent = ({ features }) => {
  const dispatch = useDispatch();

  return (
    /* Card layout and heading */

    <div className="bg-white p-4 rounded col-span-2 row-span-5">
      {Object.entries(features).map(([key, value]) => {
        return (
          <div key={key}>
            <h5 className="text-black m-t-4">{key}</h5>
            <div className="border-bottom border-primary pb-2 mb-4 mr-20">
              {/* Render feature checkboxes */}

              {value.map((feature) => {
                return (
                  <div className="flex justify-between m-2" key={feature}>
                    <div>
                      <Checkbox
                        onChange={() => dispatch(featureCheckboxClick(feature))}
                      />
                      <span className="pl-2 text-lg">{feature}</span>
                    </div>
                  </div>
                );
              })}
            </div>
          </div>
        );
      })}
    </div>
  );
};

export default connect()(FeaturesComponent);

checkbox-component:

import React from 'react';

import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import { faCheck } from '@fortawesome/free-solid-svg-icons';

const Checkbox = () => {
  return (
    <label htmlFor="check-box-1" className="cursor-pointer relative">
      <input
        type="checkbox"
        className="check-box-1 appearance-none h-4.5 w-4.5 border-2 border-primary rounded-sm relative translate-y-0.5"
      />
      <FontAwesomeIcon
        icon={faCheck}
        className="-translate-x-4 translate-y-0.5 h-4.5 w-4.5 text-sm absolute text-white text-opacity-0 transition check-1 duration-200"
      />
    </label>
  );
};

export default Checkbox;

css tailwind directives (should be readable, even if you never worked with tailwind):

@tailwind components;
@tailwind utilities;

.check-box-1:checked {
  @apply bg-primary;
}

.check-box-1:checked ~ .check-1 {
  @apply text-opacity-100;
}

That´s all the code. Like I said, I´d usually work with a useState array or so, but It´s kinda hard to control it, bc there is so much nesting in the mapping, or am I thinking too complicated?

I´m honestly clueless and am glad for any help I can get, cheers!

1 Answers

I hope this helps

import { NextPage } from "next"
import { useState } from "react"
import CheckboxList from "../../../components/learn22/CheckboxList"

const myFoodList = [
    '김치',
    '고구마',
    '감자',
    '피자',
    '햄버거',
    '라면',
    '제육볶음',
    '삼계탕',
    '닭곰탕',
    '추어탕'
]

const MyCheckList: NextPage = () => {

    const [checkedFoods, setCheckedFoods] = useState<string[]>([])

    const onMyFoodChecked = (checked : string[]) => {
        setCheckedFoods(checked)
        console.log(checked)
    }

    return(
        <CheckboxList
            checkedFoods ={checkedFoods}
            onCheck = {onMyFoodChecked}
            foods = {myFoodList}
        />
    )
}

export default MyCheckList;

import { FunctionComponent } from "react";

interface Props {
    checkedFoods ?: string[];
    onCheck: (checked : string[]) => void;
    foods ?: string[];
}
 
const CheckBoxList : FunctionComponent<Props> = ({
    checkedFoods =[],
    onCheck,
    foods =[]
}) => {

    return (<ol>{foods.map((food, idx)=>
        <li key={food + '-' + idx}>
            <input type='checkbox' checked={checkedFoods?.includes(food)}onChange={(e)=>{
                if(e.target.checked){
                    onCheck([...checkedFoods!, food])
                } else{
                    onCheck(checkedFoods.filter((_food)=> _food !== food));
                }
            }}/>
            <span>{food}</span>
        </li>
    )}
    </ol>  );
}
 
export default CheckBoxList;

[blog post that shows how to Handle multiple checkbox components in React][1] [1]: https://codemasterkimc.tistory.com/459

Related