如何使用一个不确定的React检查框(附代码示例)

182 阅读2分钟

一个简短的React教程,通过实例为初学者介绍如何创建一个不确定的React Checkbox,它使用不确定的状态(也叫三态)。

让我们从之前教程中的一个复选框例子开始:

const App = () => {
  const [checked, setChecked] = React.useState(false);

  const handleChange = () => {
    setChecked(!checked);
  };

  return (
    <div>
      <Checkbox
        label="Value"
        value={checked}
        onChange={handleChange}
      />

      <p>Is checked? {checked.toString()}</p>
    </div>
  );
};

const Checkbox = ({ label, value, onChange }) => {
  return (
    <label>
      <input type="checkbox" checked={value} onChange={onChange} />
      {label}
    </label>
  );
};

现在我们想扩展这个复选框的功能,以处理三态而不是双态。首先,我们需要将我们的状态从布尔值转换为枚举值,因为只有这样我们才能创建一个三态。

const CHECKBOX_STATES = {
  Checked: 'Checked',
  Indeterminate: 'Indeterminate',
  Empty: 'Empty',
};

const App = () => {
  const [checked, setChecked] = React.useState(CHECKBOX_STATES.Empty);

  const handleChange = () => {
    let updatedChecked;

    if (checked === CHECKBOX_STATES.Checked) {
      updatedChecked = CHECKBOX_STATES.Empty;
    } else if (checked === CHECKBOX_STATES.Empty) {
      updatedChecked = CHECKBOX_STATES.Checked;
    }

    setChecked(updatedChecked);
  };

  return (
    <div>
      <Checkbox
        label="Value"
        value={checked}
        onChange={handleChange}
      />

      <p>Is checked? {checked}</p>
    </div>
  );
};

const Checkbox = ({ label, value, onChange }) => {
  return (
    <label>
      <input
        type="checkbox"
        checked={value === CHECKBOX_STATES.Checked}
        onChange={onChange}
      />
      {label}
    </label>
  );
};

我们有和以前一样的行为,但是使我们的复选框能够有两个以上的状态。

接下来是复选框的不确定状态。不幸的是,它不能通过HTML来分配,我们需要在这里使用一个强制性的DOM操作。幸运的是,React有Refs的概念,使React开发者能够访问DOM元素:

const Checkbox = ({ label, value, onChange }) => {
  const checkboxRef = React.useRef();

  return (
    <label>
      <input
        ref={checkboxRef}
        type="checkbox"
        checked={value === CHECKBOX_STATES.Checked}
        onChange={onChange}
      />
      {label}
    </label>
  );
};

通过对复选框元素的访问,我们可以强制性地设置和取消复选状态,而不是以声明的方式使用HTML:

const Checkbox = ({ label, value, onChange }) => {
  const checkboxRef = React.useRef();

  React.useEffect(() => {
    if (value === CHECKBOX_STATES.Checked) {
      checkboxRef.current.checked = true;
    } else {
      checkboxRef.current.checked = false;
    }
  }, [value]);

  return (
    <label>
      <input ref={checkboxRef} type="checkbox" onChange={onChange} />
      {label}
    </label>
  );
};

React的useEffect Hook在每次依赖数组(这里是:value )中的变量发生变化时都会执行其传递的副作用函数。然后在侧效果函数中,我们评估该值:如果是选中的,我们以编程方式将复选框的内部HTML状态设置为选中;反之则为未选中的状态。

最后,我们也可以用这种方式来分配不确定的状态:

const Checkbox = ({ label, value, onChange }) => {
  const checkboxRef = React.useRef();

  React.useEffect(() => {
    if (value === CHECKBOX_STATES.Checked) {
      checkboxRef.current.checked = true;
      checkboxRef.current.indeterminate = false;
    } else if (value === CHECKBOX_STATES.Empty) {
      checkboxRef.current.checked = false;
      checkboxRef.current.indeterminate = false;
    } else if (value === CHECKBOX_STATES.Indeterminate) {
      checkboxRef.current.checked = false;
      checkboxRef.current.indeterminate = true;
    }
  }, [value]);

  return (
    <label>
      <input ref={checkboxRef} type="checkbox" onChange={onChange} />
      {label}
    </label>
  );
};

别忘了,首先要在状态变化时分配适当的值:

const App = () => {
  const [checked, setChecked] = React.useState(CHECKBOX_STATES.Empty);

  const handleChange = () => {
    let updatedChecked;

    if (checked === CHECKBOX_STATES.Checked) {
      updatedChecked = CHECKBOX_STATES.Empty;
    } else if (checked === CHECKBOX_STATES.Empty) {
      updatedChecked = CHECKBOX_STATES.Indeterminate;
    } else if (checked === CHECKBOX_STATES.Indeterminate) {
      updatedChecked = CHECKBOX_STATES.Checked;
    }

    setChecked(updatedChecked);
  };

  return (
    <div>
      <Checkbox
        label="Value"
        value={checked}
        onChange={handleChange}
      />

      <p>Is checked? {checked}</p>
    </div>
  );
};

就这样了。通过引入不确定状态,我们将我们的React复选框组件从双状态转变为三状态。我希望这个教程对你有用,如果你正好需要一个有三种状态的复选框。