반응형

export interface checkbox {
  text: string;
  code: string;
}

const weekOption: checkbox[] = [
  { text: '일', code: 'week1' },
  { text: '월', code: 'week2' },
  { text: '화', code: 'week3' },
  { text: '수', code: 'week4' },
  { text: '목', code: 'week5' },
  { text: '금', code: 'week6' },
  { text: '토', code: 'week7' },
];

const Checkboxes = ({
  checkboxOption,
  disabled,
}: {
  checkboxOption: checkbox[];
  disabled: boolean;
}) => {
  const [checkbox, setCheckbox] = useState<string[]>([]);

  const addCheckboxOption = (checked: CheckedState, value: string) => {
    let updatedOption: string[];

    if (checked) {
      updatedOption = [...checkbox, value];
    } else {
      updatedOption = checkbox.filter((el) => el !== value);
    }

    // checkboxOption에 적힌 순서대로 정렬 해서 추가
    const sortedCheckbox = checkboxOption.filter((checkbox) =>
      updatedOption.includes(checkbox.code),
    );

    setCheckbox(sortedCheckbox.map((checkbox) => checkbox.code));
  };

  return (
    <>
      {checkboxOption.map((checkbox) => (
        <React.Fragment key={checkbox.code}>
          <Checkbox
            id={checkbox.code}
            checked={disabled ? disabled : undefined}
            disabled={disabled}
            onCheckedChange={(e) => addCheckboxOption(e, checkbox.code)}
          />
          <label
            htmlFor={checkbox.code}
            className="text-sm font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70"
          >
            {checkbox.text}
          </label>
        </React.Fragment>
      ))}
    </>
  );

Checkbox박스 컴포넌트의 경우 https://ui.shadcn.com/에서 가져온 거라 그 부분은 본인이 만든 체크박스 컴포넌트에 맞게 만드시면 됩니다

 


 

interface CheckBoxActions {
  [key: string]: ActionCreatorWithPayload<string[], string>;
}

const checkboxActions: CheckBoxActions = {
  groupWeek: groupInfoSlice.actions.setExposureWeek,
  groupExposureArea: groupInfoSlice.actions.setExposureArea,
};

type SelectorFunction = (state: RootState) => string[];

const stateSelectors: Record<string, SelectorFunction> = {
  groupWeek: (state) => state.groupInfo.exposureWeek,
  groupExposureArea: (state) => state.groupInfo.exposureArea,
};

const Checkboxes = ({
  checkboxOption,
  actionName,
  disabled,
}: {
  checkboxOption: checkbox[];
  actionName: string;
  disabled: boolean;
}) => {
  const dispatch = useAppDispatch();
  const action = checkboxActions[actionName];

  const checkbox = useSelector((state: RootState) => {
    const selector = stateSelectors[actionName];
    return selector ? selector(state) : [];
  });

  const addCheckboxOption = (checked: CheckedState, value: string) => {
    let updatedOption: string[];

    if (checked) {
      updatedOption = [...checkbox, value];
    } else {
      updatedOption = checkbox.filter((el) => el !== value);
    }

    // 정렬 추가
    const sortedCheckbox = checkboxOption.filter((checkbox) =>
      updatedOption.includes(checkbox.code),
    );

    const result = sortedCheckbox.map((checkbox) => checkbox.code);
    dispatch(action(result));
  };

  return (
    <>
      {checkboxOption.map((checkbox) => (
        <React.Fragment key={checkbox.code}>
          <Checkbox
            id={checkbox.code}
            checked={disabled ? disabled : undefined}
            disabled={disabled}
            onCheckedChange={(e) => addCheckboxOption(e, checkbox.code)}
          />
          <label
            htmlFor={checkbox.code}
            className="text-sm font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70"
          >
            {checkbox.text}
          </label>
        </React.Fragment>
      ))}
    </>
  );

여기는 전역 상태관리 Redux를 사용한 경우 컴포넌트를 전역 상태관리할 수 있게 나름대로 코드를 만들어봤습니다

 

  • actionName 상태관리 변수명에 따라 useSelector로 값을 가져오며 상태관리 변수명에 따라 값을 Set할 수 있게 action을 설정해줍니다
  • checkboxActions, stateSelectors에서 actionName에 대한 "키"를 입력해주면 됩니다

 

반응형