mercredi 18 octobre 2023

How to make each component shared state multiple controlled checkbox selection unique in react?

i have several components on the left side. I am running map on them. Each component has a switch.so on the basis of component id after clicking on switch a list of checkboxes open at right side. then again i am also running map on checkboxes because this data is coming from backend. for example component-1 have list of checkboxes with the following name. checkbox-1 checkbox-2 if i select the checkbox-1 and then click on component-2 switch, so by this component-2 list of checkboxes will show. the issue is component-2 checkbox name also will be checked if component-2 have checkbox name same like component-1. how to keep them unique? i want each component checkbox selection to be unique. this is one i did so far. (1) i am passing key to components.so whenever id change react rerender the ui.but its not working. (2) currently my checkbox state is in parent component,i looked into react documentation, according to it the state should be local to component.i move the checkbox state into checkbox component then my issue was fixed. But i need checkbox selection in parent because i am sharing this with other components. (3) then i implement the redux-saga. but still same issue, then i implemented context api, this also didn't resolve my issue.

i am sharing my handlechange code. this is how managing them.

  const handleChange = event => {
    const { name, checked } = event.target;
    if (checked) {
      setCheckedItems({ ...checkedItems, [name]: true });
    } else {
      const { [name]: deletedItem, ...updatedCheckedItems } = checkedItems;
      setCheckedItems(updatedCheckedItems);
    }
  };

(4) then i thought maybe i should make a data structure like so, each component unique id should have its own checkbox selection when user checked any checkbox. this is that code.

  const handleChange = (event, componentId, index) => {
    const { name, checked } = event.target;

    setCheckboxIndex(index);

    // Update the state using the componentId to ensure uniqueness
    setCheckedItems(prevItems => {
      // Get the previous state for the component or initialize it
      const componentState = prevItems[componentId] || { checkboxes: {} };
      // Clone the previous component state
      const updatedComponentState = { ...componentState };

      if (checked) {
        updatedComponentState.checkboxes = {
          ...updatedComponentState.checkboxes,
          [name]: true,
        };
      } else {
        // Remove the checkbox from the component's state
        const {
          [name]: deletedItem,
          ...updatedCheckboxes
        } = updatedComponentState.checkboxes;
        updatedComponentState.checkboxes = updatedCheckboxes;
      }

      // Update the overall state with the new component state
      return {
        ...prevItems,
        [componentId]: updatedComponentState,
      };
    });
  };

but this one also didn't resolve my issue. this also code currently in context.js now i am sharing my how my component looks alike.

 (toggleMenu === 'feedback' &&
              Object.keys(feedback).includes(String(q.id))) ||
            (q.question.question_type === 'assignment' &&
              toggleAll === 'auto') ? (
              <Grid item xs={5} className={classes.questionWrapper} key={q.id}>
                <NewFeedback
                  key={q.id}
                  assignmentIndex={qidx}
                  markingData={automatedMarkingData}
                  questionId={q.question.id}
                  qId={qId}
                  fetchMarkingData={fetchMarkingData}
                  status={assignmentStatus}
                />
              </Grid>

whenever user click on component switch i am updating this state. feedback then on the basis of id inside feedback i am opening checkbox component.

the component NewFeedback is the component where checkbox component is, with name of sidebar.js

<SideBar
        bow={bow}
        checkedItems={checkedItems}
        handleSelectAll={handleSelectAll}
        handleChange={handleChange}
        allSelected={allSelected}
        assignmentId={markingData.question_submission}
        assignmentIndex={assignmentIndex}
        checkboxIndex={checkboxIndex}
      />

this is my sidebar.js code

import React, { useContext } from 'react';
import {
  Box,
  Checkbox,
  Divider,
  FormControlLabel,
  FormGroup,
  LinearProgress,
  Paper,
  Typography,
} from '@material-ui/core';
import styles from './styles.css';
import { LessonContext } from '../../LessonViewer/GoProgressQuizResult/Context';

export const SideBar = ({
  bow,
  checkedItems,
  handleSelectAll,
  handleChange,
  allSelected,
  assignmentId,
  assignmentIndex,
  checkboxIndex,
}) => {
  return (
    <Paper elevation={0} className={`${styles.FeedbackSideMenu}`}>
      <Box p={1}>
        <Typography align="center">
          <b>All BOW</b>
        </Typography>
      </Box>
      <Divider style= />
      <Box style=>
        <FormGroup>
          <FormControlLabel
            style=
            control={
              <Checkbox
                checked={allSelected}
                onChange={handleSelectAll}
                name="selectAll"
                color="primary"
              />
            }
            label="Select All"
          />
        </FormGroup>
        {bow.map((v, index) => {
          // const isChecked =
          //   (checkedItems[assignmentId] &&
          //     checkedItems[assignmentId].checkboxes[v.bow_name]) ||
          //   false;

          // console.log('isChecked', isChecked);
          return (
            <div key={v.id}>
              <Box className={`${styles.FeedbackOption}`}>
                <Box
                  display={'flex'}
                  justifyContent="space-between"
                  alignItems="center"
                >
                  <Checkbox
                    id={v.id}
                    // checked={checkedItems[`${v.bow_name}_${v.id}`] || false}
                    checked={checkedItems[v.bow_name] || false}
                    // checked={label === v.bow_name ? true : false}
                    // checked={isChecked}
                    onChange={e => handleChange(e, assignmentId, index)}
                    name={v.bow_name}
                    color="primary"
                  />
                  <Typography>
                    <b>{v.bow_name}</b>
                  </Typography>
                  <Box bgcolor={`${v.color}`} width={20} height={20} />
                </Box>

                <Typography>
                  <small>{v.sum_count} count</small>
                </Typography>
                <LinearProgress
                  variant="determinate"
                  value={v.sum_count ? v.sum_count : 0}
                />
              </Box>
              <Divider style= />
            </div>
          );
        })}
      </Box>
    </Paper>
  );
};

sorry i cant make sandbox because my actualy codebase is pretty big. here's my ui images for better understanding. enter image description here




Aucun commentaire:

Enregistrer un commentaire