【问题标题】:Toggle booleans and update obj with useState()使用 useState() 切换布尔值并更新对象
【发布时间】:2021-06-22 10:23:16
【问题描述】:

目前,我有许多复选框,这些复选框显然都与需要在 onSubmit 上传递的布尔值相关。我最初有这样的事情:

  const [value, setValue] = React.useState({
    alpha: true,
    beta: false,
    charlie: false,
    // twenty or so more
  });

  ...

  <CheckboxComp
    aria-label="id"
    checked={value.alpha}
    onChange={() => setValue({ alpha: !value.alpha})}
    label="id"
  />

这让我大吃一惊:

Warning: A component is changing a controlled input to be uncontrolled. This is likely caused by the value changing from a defined to undefined, which should not happen. Decide between using a controlled or uncontrolled input element for the lifetime of the component. 

然后我遇到了this

- Through Input

        const [state, setState] = useState({ fName: "", lName: "" });
        const handleChange = e => {
            const { name, value } = e.target;
            setState(prevState => ({
                ...prevState,
                [name]: value
            }));
        };

        <input
            value={state.fName}
            type="text"
            onChange={handleChange}
            name="fName"
        />
        <input
            value={state.lName}
            type="text"
            onChange={handleChange}
            name="lName"
        />
   ***************************

 - Through onSubmit or button click
    
        setState(prevState => ({
            ...prevState,
            fName: 'your updated value here'
         }));

这几乎和我得到的一样接近,但我在用输入字符串的东西切换真/假时遇到了麻烦。任何帮助,我知道这是一个愚蠢的问题,但它比继续使用 useState(false) x20 好得多,这是最远离优化的事情。

现在我有这样的东西!

  const [value, setValue] = React.useState({
    alpha: true,
    beta: false,
    charlie: false,
  });

  const handleChange = e => {
      const { name, value } = e.target;
      setValue(prevState => ({
          ...prevState,
          [name]: value
      }));
  };

  console.log(value)
  
  ...

  <CheckboxComp
    aria-label="id"
    checked={value.alpha}
    onChange={handleChange}
    name="alpha"
    label="id"
  />

但 console.log 显示

alpha: "true"

【问题讨论】:

  • 这能回答你的问题吗? React - changing an uncontrolled input。此外,您的 onChange 调用 () =&gt; setValue({ alpha: !value.alpha}) 会覆盖除 alpha 之外的所有其他属性。

标签: javascript reactjs react-hooks


【解决方案1】:

正如我在评论中指出的那样,您的 setValue 调用将覆盖所有属性,但明确命名的属性除外。您展示的将回调传递给setValue 的示例不仅仅是“仅用于字符串”,它只是一种在维护所有其他属性的同时为单个属性分配新值的方法。请参阅:destructuring assignmentspread syntax (...)

这是一个快速工作的 sn-p。

function App() {
  const [value, setValue] = React.useState({
    alpha: true,
    beta: false,
    charlie: false,
    // twenty or so more
  });

  const checkChange = (e) => {
    const { id, checked } = e.target;
    setValue(prevValue => ({ ...prevValue, [id]: checked }))
  };

  return (
    <div>
      <form>
        {Object.keys(value).map(k =>
          <div key={k}>
            <input type="checkbox" id={k} name={k} checked={value[k]} onChange={checkChange} />
            <label for={k}>{k}</label>
          </div>
        )}
      </form>
    </div>
  );
}

ReactDOM.render(
  <App />,
  document.getElementById("root")
);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.4/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.4/umd/react-dom.production.min.js"></script>

<div id="root"></div>

【讨论】:

  • 让我们说,我要手动编写每个复选框,而不是映射每个复选框,我需要进行哪些更改?
  • 将所有ks替换为状态值的属性名。例如。 &lt;input type="checkbox" id="alpha" name="alpha" checked={value.alpha} onChange={checkChange} /&gt;
【解决方案2】:

问题出在 Checkbox 组件的这段代码中:

    onChange={() => setValue({ alpha: !value.alpha})}

当您通过传递{ alpha: !value.alpha } 更新状态时,它实际上是在您修改对象时从对象中删除所有其他键,而不是修改键的特定值同时保留所有其他键一样的

您应该使用扩展运算符或Object.assign来提供修改后的新对象。

对于您当前的代码,当setValue 被触发时,您的状态对象会留下{ alpha: false },而它应该是{ alpha: false, beta: false, ...}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-12-27
    • 1970-01-01
    • 2021-10-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-09-02
    相关资源
    最近更新 更多