如何在react挂钩中捕获一组状态变化(附代码)

71 阅读1分钟

下面的例子有两个 "表单"。一个是first name ,一个是last name ,有一个单一的输入和OK、Cancel按钮。但是想象一下,在每个表单中还有更多的数据需要收集。

我正在捕捉他们在一个字段中输入时的当前状态(像正常情况一样),以及每个表单先前接受的值。先前接受是指用户点击 "好 "时的状态。这样,如果他们在随后的状态变化中点击取消,我就可以将其恢复到之前接受的值。

另外,这些表单是相互排斥的,这样,当你接受一个表单时,存储在另一个表单中的任何数据都被重置为空状态。

寻找一种方法来减少状态和参考变量。

请看 codesandbox 上的例子

有没有一种方法可以让所有的数据都用一个对象来进行更新,以减少代码行数?现在我只能用例子中所示的单个字符串状态和参考变量来工作:

type DialogTypes = "FIRST" | "LAST" | "";

function Options() {
  const [firstNameState, setFirstNameState] = React.useState("");
  const [lastNameState, setLastNameState] = React.useState("");
  const firstNameRef = React.useRef("");
  const lastNameRef = React.useRef("");
  const [currentChoice, setCurrentChoice] = React.useState<DialogTypes>("");

  function handleFirstNameChange(e: React.ChangeEvent<HTMLInputElement>) {
    setFirstNameState(e.target.value);
  }

  function handleFirstNameOkClick() {
    firstNameRef.current = firstNameState;
    setCurrentChoice("FIRST");

    // reset state and ref for other forms:
    setLastNameState("");
    lastNameRef.current = "";
  }

  function handleFirstNameCancelClick() {
    // reverting what they accepted before (if anything)
    setFirstNameState(firstNameRef.current);
  }

  function handleLastNameChange(e: React.ChangeEvent<HTMLInputElement>) {
    setLastNameState(e.target.value);
  }

  function handleLastNameOkClick() {
    lastNameRef.current = lastNameState;
    setCurrentChoice("LAST");

    // reset state and ref for other form:
    setFirstNameState("");
    firstNameRef.current = "";
  }

  function handleLastNameCancelClick() {
    // reverting what they accepted before (if anything)
    setLastNameState(lastNameRef.current);
  }

  return (
    <>
      <Rules />
      <div id="choice-a-form" style={formStyles}>
        <div>
          <label style={{ fontWeight: "bold" }}>First Name: </label>
          <input
            value={firstNameState}
            onChange={handleFirstNameChange}
            type="text"
          />
          <button onClick={handleFirstNameOkClick}>Ok</button>
          <button onClick={handleFirstNameCancelClick}>Cancel</button>
          {currentChoice === "FIRST" && (
            <label style={{ color: "red" }}> Selected Option</label>
          )}
        </div>

        <div>first name current value (state): {firstNameState}</div>
        <div>last name previous value (ref): {firstNameRef.current}</div>
      </div>
      <div id="choice-b-form" style={formStyles}>
        <div>
          <label style={{ fontWeight: "bold" }}>Last Name: </label>
          <input
            value={lastNameState}
            onChange={handleLastNameChange}
            type="text"
          />
          <button onClick={handleLastNameOkClick}>Ok</button>
          <button onClick={handleLastNameCancelClick}>Cancel</button>
          {currentChoice === "LAST" && (
            <label style={{ color: "red" }}> Selected Option</label>
          )}
        </div>

        <div>last name current value (state): {lastNameState}</div>
        <div>last name Previous Value (ref): {lastNameRef.current}</div>
      </div>

      <div style={{ width: "50%", padding: "12px" }}>
        <button>Send Selection</button>{" "}
        <em> (this passes object to parent via callback)</em>
      </div>
    </>
  );
}

export default Options;