在React中以前的状态和参考文献用于作为一个单元的还原选项

176 阅读2分钟

我想做一个组件,允许用户从不同的对话框中选择被触发的选项。它是相互排斥的,所以一旦他们选择了一个,输入数据,并点击OK,任何以前可能在其他对话框中接受的选择都会被重置。但在一个对话框的上下文中,他们之前接受的修改应该显示出来,而且 "当前 "对话框的后续修改应该是可以取消的。

这里是这个想法的一个非常简化的版本,它正在按预期工作。它可能更好地解释了这个意图。请看 codesandbox 上的例子

问题:

  1. 是否有更好的方法来恢复他们所选择的内容?我不喜欢有10个单独的变量和参照物,我必须在每个对话框每个处理程序中重置。

  2. 有没有一种方法可以让所有对话框的所有数据都使用一个单一的对象?现在我只能让它在单个状态和参考变量下工作。

我真正的组件将有不止一个文本输入。我将收集的数据并回调到父组件,看起来像这样:

const data = {
  options1: {
    name: string,
    list: string[]
  },
  options2: string[],
  options3: string,
  options4: string,
  options5: string[], 
}

上面的每个键都是单个对话框所接受的内容,并且可以被还原(直到他们选择另一个并点击确定)。

我一直在为这个问题挠头。我从来没有把以前的状态作为一个组来挂起,然后再恢复它。状态是指他们的整个选择,而不仅仅是文本字段中的最后一次按键。

这似乎比我原来想象的要复杂。我知道一定有一个更聪明的方法,但我仍在学习反应,我仍然有差距。

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 ALL other dialogs:
    setLastNameState("");
    lastNameRef.current = "";
  }

  function handleFirstNameCancelClick() {
    // reverting what they might have accepted
    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 ALL other dialogs:
    setFirstNameState("");
    firstNameRef.current = "";
  }

  function handleLastNameCancelClick() {
    // reverting what they might have accepted
    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;