會有以下幾種狀態:
import React, { Fragment } from "react";
import isNumber from 'lodash/isNumber';
import styled from "styled-jss";
import propTypes from "prop-types";
import FromLabel from "../FromLabel";
import FormGroup from "../FormGroup";
import breakpoint from "../constant/breakpoint";
const StyledCheck = styled("label")({
  position: "relative",
  display: "flex",
  paddingLeft: 30,
  opacity: ({ disabled }) => disabled ? 0.5 : 1,
  marginBottom: ({ theme }) => theme.getSpacing(1),
  paddingRight: ({ theme }) => theme.getSpacing(1),
  alignItems: "center",
  "&:before": {
    position: "absolute",
    content: '""',
    left: 0,
    width: 8,
    height: 8,
    margin: ({ theme }) => theme.getSpacing(1),
    border: ({ theme, checked }) =>
      `5px solid ${checked ? theme.colors.primary : theme.colors.grey1}`,
  },
  [breakpoint.mediaLG]: {
    marginBottom: ({ theme }) => theme.getSpacing(0),
  },
});
const CheckItems = ({ items, name, disabled, onChange, values: currentValues }) => {
  return items.map((item, index) => {
    const itemValue = isNumber(item.value) ? item.value.toString() : item.value;
    const checked = currentValues.includes(itemValue);
    const ID = `${name}_${item.value}_${index}`;
    return (
      <Fragment key={`radios_${index}`}>
        <StyledCheck htmlFor={ID} checked={checked} disabled={disabled}>
          {item.label}
        </StyledCheck>
        <input
          type='checkbox'
          id={ID}
          name={name}
          value={item.value}
          onChange={onChange}
          checked={checked}
          disabled={disabled}
          style={{ display: "none" }}
        />
      </Fragment>
    );
  });
};
const CheckGroup = ({
  name,
  items,
  label,
  values,
  onChange,
  required,
  disabled,
  ...props
}) => {
  return (
    <FormGroup>
      <FromLabel required={required}>{label}</FromLabel>
      <CheckItems values={values} items={items} name={name} disabled={disabled} onChange={onChange} />
    </FormGroup>
  );
};
CheckGroup.propTypes = {
  label: propTypes.string,
  disabled: propTypes.bool,
  items: propTypes.arrayOf(
    propTypes.shape({
      label: propTypes.string,
      value: propTypes.oneOfType([propTypes.number, propTypes.string]),
    })
  ),
  values: propTypes.arrayOf(
    propTypes.oneOfType([propTypes.number, propTypes.string])
  ),
  onChange: propTypes.func,
};
CheckGroup.defaultProps = {
  label: "",
  items: [],
  values: [],
  disabled: false,
  onChange: () => false,
};
export default CheckGroup;
import React, { Fragment, useState } from "react";
import theme from "../../lib/theme";
import FormControl from "../../lib/FormControl";
import ThemeProvider from "../../lib/ThemeProvider";
import CheckGroup from "../../lib/CheckGroup";
const CheckItems = [
  {
    label: "Radio 1",
    value: 1,
  },
  {
    label: "Radio 2",
    value: 2,
  },
  {
    label: "Radio 3",
    value: 3,
  },
];
const handleOnChange = (values, setValue) => ({ target: { value } }) => {
  const newValues = values.includes(value)
    ? values.filter((selectedValue) => selectedValue !== value)
    : [value, ...values];
    setValue(newValues);
};
const Provider = (props) => {
  return <ThemeProvider theme={theme}>{props.children}</ThemeProvider>;
};
const TemplateForm = (args) => {
  const [values, setValues] = useState([]);
  const onChange = handleOnChange(values, setValues);
  return (
    <Provider>
      <Fragment>
        <FormControl>
          <CheckGroup {...args} values={values} onChange={onChange} />
          <CheckGroup {...args} name='disabledTest' values={values} onChange={onChange} disabled/>
        </FormControl>
      </Fragment>
    </Provider>
  );
};
const Template = (args) => {
  const [values, setValues] = useState([]);
  const onChange = handleOnChange(values, setValues);
  return (
    <Provider>
      <Fragment>
        <FormControl>
          <CheckGroup {...args} values={values} onChange={onChange} />
        </FormControl>
      </Fragment>
    </Provider>
  );
};
export const Default = TemplateForm.bind({});
Default.args = {
  name: "username",
  items: CheckItems,
};
export const LabelCheck = Template.bind({});
LabelCheck.args = {
  name: "labelItems",
  items: CheckItems,
  label: "label",
  required: true,
};
// 你的頁面標題
export default {
  component: CheckGroup,
  title: "Form/Check",
};
結果如下:

import React, { Fragment } from "react";
import styled from "styled-jss";
import propTypes from "prop-types";
import FromLabel from "../FromLabel";
import FormGroup from "../FormGroup";
import breakpoint from "../constant/breakpoint";
const StyledRadio = styled("label")({
  position: "relative",
  display: "flex",
  paddingLeft: 30,
  opacity: ({ disabled }) => disabled ? 0.5:1,
  marginBottom: ({ theme }) => theme.getSpacing(1),
  paddingRight: ({ theme }) => theme.getSpacing(1),
  alignItems: "center",
  "&:before": {
    position: "absolute",
    content: '""',
    left: 0,
    width: 8,
    height: 8,
    borderRadius: 10,
    margin: ({ theme }) => theme.getSpacing(1),
    border: ({ theme, checked }) =>
      `5px solid ${checked ? theme.colors.primary : theme.colors.grey1}`,
  },
  [breakpoint.mediaMD]: {
    marginBottom: ({ theme }) => theme.getSpacing(0),
  },
});
const RadioItems = ({
  items,
  name,
  onChange,
  disabled,
  value: currentValue,
}) => {
  return items.map((item, index) => {
    const checked = currentValue === item.value;
    const ID = `${name}_${item.value}_${index}`;
    return (
      <Fragment key={`radios_${index}`}>
        <StyledRadio htmlFor={ID} checked={checked} disabled={disabled}>
          {item.label}
        </StyledRadio>
        <input
          type='radio'
          id={ID}
          name={name}
          value={item.value}
          onChange={onChange}
          checked={checked}
          disabled={disabled}
          style={{ display: "none" }}
        />
      </Fragment>
    );
  });
};
const RadioGroup = ({
  name,
  items,
  label,
  value,
  onChange,
  required,
  disabled,
  ...props
}) => {
  return (
    <FormGroup>
      <FromLabel required={required}>{label}</FromLabel>
      <RadioItems
        name={name}
        value={value}
        items={items}
        onChange={onChange}
        disabled={disabled}
      />
    </FormGroup>
  );
};
RadioGroup.propTypes = {
  label: propTypes.string,
  disabled: propTypes.bool,
  items: propTypes.arrayOf(
    propTypes.shape({
      label: propTypes.string,
      value: propTypes.oneOfType([propTypes.number, propTypes.string]),
    })
  ),
  value: propTypes.oneOfType([propTypes.number, propTypes.string]),
  onChange: propTypes.func,
};
RadioGroup.defaultProps = {
  label: "",
  value: "",
  items: [],
  disabled: false,
  onChange: () => false,
};
export default RadioGroup;
import React, { Fragment, useState } from "react";
import theme from "../../lib/theme";
import FormControl from "../../lib/FormControl";
import ThemeProvider from "../../lib/ThemeProvider";
import RadioGroup from '../../lib/RadioGroup';
const RadioItems = [
  {
    label: 'Radio 1',
    value: 1
  },
  {
    label: 'Radio 2',
    value: 2
  },
  {
    label: 'Radio 3',
    value: 3
  }
]
const handleOnChange = (setValue) => ({ target: { value }}) => {
  setValue(parseInt(value, 10));
}
const Provider = (props) => {
  return <ThemeProvider theme={theme}>{props.children}</ThemeProvider>;
};
const TemplateForm = (args) => {
  const [value, setValue] = useState(1);
  const onChange = handleOnChange(setValue);
  return (
    <Provider>
      <Fragment>
        <FormControl>
            <RadioGroup {...args} value={value} onChange={onChange}/>
            <RadioGroup {...args} disabled name='disableTest' value={value} onChange={onChange}/>
        </FormControl>
      </Fragment>
    </Provider>
  );
};
const Template = (args) => {
  const [value, setValue] = useState(1);
  const onChange = handleOnChange(setValue);
  return (
    <Provider>
      <Fragment>
        <FormControl>
            <RadioGroup {...args} value={value} onChange={onChange}/>
        </FormControl>
      </Fragment>
    </Provider>
  );
};
export const Default = TemplateForm.bind({});
Default.args = {
  name: 'username',
  items: RadioItems
}
export const LabelRadio = Template.bind({});
LabelRadio.args = {
  name: 'labelItems',
  items: RadioItems,
  label: 'label',
  required: true,
}
// 你的頁面標題
export default {
  component: RadioGroup,
  title: "Form/Radio",
};
結果如下:
