【问题标题】:Input onChange handler handler don't work - React Hooks输入 onChange 处理程序处理程序不起作用 - React Hooks
【发布时间】:2020-07-25 17:31:48
【问题描述】:

我的 Input 处理程序在前 2 次更改时工作正常,在第 3 次更改时会引发错误:

代码如下:

const [fields, setFields] = useState({
    email: '',
    password: ''
  });

  ...

  const handleFieldChange = useCallback((field, e) => {
    console.log(e);
    setFields(prevstate => ({
      ...prevstate,
      [field]: e.target.value
    }))
  }, [setFields]);

  ...


  <TextField
     className={cx('input')}
     label="Email"
     value={fields.email}
     variant="outlined"
     onChange={(e) => handleFieldChange('email',e)}
  />

到目前为止,我尝试删除 useCallback 并且它的行为方式相同。

【问题讨论】:

  • &lt;TextField/&gt; 来自某种 UI 框架,您需要检查他们的文档,无论他们是否发送 dom 的值!我认为它会在&lt;input/&gt; 中正常工作
  • 是的,它来自 Material UI,我会检查
  • @pageNotfoUnd 我尝试了常规输入,但仍然无法正常工作:/

标签: reactjs input react-hooks


【解决方案1】:

是的!我发现依赖项必须是它在这里起作用的值`

const handleFieldChange = useCallback((field, e) => {
    console.log(e);
    setFields(prevstate => ({
      ...prevstate,
      [field]: e.target.value
    }))
  }, [fields.email]);`

顺便说一句,useCallback 可用于昂贵的计算,我认为这里不需要

const handleFieldChange = (field,e)=>{
 // your logic
}

这就够了!

查看此文档了解更多信息https://kentcdodds.com/blog/usememo-and-usecallback/

【讨论】:

  • const handleFieldChange = (field, e) =&gt; setFields(prevstate =&gt; ({ ...prevstate, [field]: e.target.value })) 这肯定可以工作
  • 顺便说一句,我得到了一个解决方案,但我不知道它有多好。我刚刚删除了setFields 中的回调并将其更改为:setFields({...fields, [field]: e.target.value})
  • 这对你来说很好,不需要useCallback
  • 你能把它移到沙箱并发送链接吗?这很奇怪,它应该可以工作
【解决方案2】:

不要使用useCallback。它会memoise函数,每次都给出相同的函数,只要依赖相同,这里不是你想要的。

这会增加很多开销,这实际上会使您的性能变慢。

Read more 关于为什么你不应该使用它,作者之一。

只需删除useCallback 位即可:

  const handleFieldChange = (field, e) => 
    setFields(prevstate => ({
      ...prevstate,
      [field]: e.target.value
    }))
  

进一步的建议是不要做奇怪的字符串处理东西来编辑状态,使用新的钩子我们可以有多个不同的状态,将它们分开更有效,代码也更可读。

const MainComponent = () => {
  const [email, setEmail] = useState("");
  const [password, setPassword] = useState("");

  return (
    <div>
      <TextField
        label="Email"
        value={email}
        onChange={e => setEmail(e.target.value)}
      />
      <TextField
        label="Password"
        value={password}
        onChange={e => setPassword(e.target.value)}
      />
    </div>
  );
};

另一种选择,以便状态位于一个对象中 - 请注意我如何避免尝试通过传递字符串键来访问状态对象,但将其保持在一个位置:


const MainComponent = () => {
  const [fields, setFields] = useState({
    email: "",
    password: "",
  });

  return (
    <div>
      <TextField
        label="Email"
        value={fields.email}
        onChange={e => setFields({ ...fields, email: e.target.value })}
      />
      <TextField
        label="Password"
        value={fields.password}
        onChange={e => setFields({ ...fields, password: e.target.value })}
      />
    </div>
  );
};

查看沙盒here

【讨论】:

  • 不,很抱歉它也没有用,我需要将我的字段信息保存在一个对象中。我只是尝试在没有回调的情况下更改状态并且它起作用了
  • 什么不起作用?为什么它们需要在一个对象中?将它们分开以便于输入更清洁,然后当您将它们发送到其他地方时,将它们连接在一起。有什么效果吗?
  • 是的,您的权利我可以按照您建议的单独方式使用它,但这意味着我不能通过输入更改带有钩子的对象?我认为有一些方法可以做到这一点
  • 是的,有一种方法可以做任何事情,就像我(和另一个答案)已经说过的那样,如果你刚刚删除 useCallback,你的原始代码大部分都可以工作
  • @RobertHovhannisyan 我添加了另一个代码 sn-p,还有一个 CodeSandbox 链接显示它工作正常。
猜你喜欢
  • 1970-01-01
  • 2021-06-22
  • 2022-12-24
  • 1970-01-01
  • 2022-11-10
  • 1970-01-01
  • 2017-08-24
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多