Javascript 如何在React中的功能组件中创建与componentDidUpdate函数类似的函数?

Javascript 如何在React中的功能组件中创建与componentDidUpdate函数类似的函数?,javascript,reactjs,use-effect,Javascript,Reactjs,Use Effect,我试图为注册表设置一条错误消息,但因为我使用的是material UI,所以我必须为我的项目使用功能组件。我在youtube上看教程,但那个家伙在用一个类组件。我成功地将大多数代码转换为一个功能组件,但我在componentDidUpdate函数中迷失了方向 我还尝试使用useEffect功能,但没有用,如果有人没有输入任何字段,单击submit按钮时,我无法显示警报/消息错误。我还得到一个错误,msg没有在注册组件中的警报组件中定义,尽管它已经在useState函数中定义 {msg ? <

我试图为注册表设置一条错误消息,但因为我使用的是material UI,所以我必须为我的项目使用功能组件。我在youtube上看教程,但那个家伙在用一个类组件。我成功地将大多数代码转换为一个功能组件,但我在componentDidUpdate函数中迷失了方向

我还尝试使用useEffect功能,但没有用,如果有人没有输入任何字段,单击submit按钮时,我无法显示警报/消息错误。我还得到一个错误,msg没有在注册组件中的警报组件中定义,尽管它已经在useState函数中定义

{msg ? <Alert color="danger">{msg}</Alert> : null}

我创建了一个带有表单字段验证和功能组件的最小示例。 注意,您可以将任何组件编写为函数和类。我个人更喜欢函数,因为它们通常更简洁

在此处运行示例:

import React,{useState}来自“React”;
从“react dom”导入react dom;
常量应用=()=>{
const[error,setError]=useState(null);
返回(
{error&&{error}
setError(“那不是电子邮件。”)}
必修的
/>
);
};
const rootElement=document.getElementById(“根”);

render(,rootElement)
useEffect
带有空依赖项的数组将
componentDidUpdate
一样运行,它将仅在组件首次装载时运行,而在组件
重新呈现时不会运行

要模拟
componentdiddupdate
,请将
错误作为依赖项提供

const [errorMsg, setErrorMsg] = useState('');

useEffect(() => {
  if (error.id === "REGISTER_FAIL") {
    setErrorMsg(props.error.msg.msg);
  }
}, [props.error])

return (
  <div className="App">
  {errorMsg && <span>{errorMsg}</span>}
  </div>
);
const[errorMsg,setErrorMsg]=useState(“”);
useffect(()=>{
如果(error.id==“REGISTER\u FAIL”){
setErrorMsg(props.error.msg.msg);
}
},[props.error])
返回(
{errorMsg&&{errorMsg}
);
我还建议您在每次提交表单时发送一个操作,并将错误消息重置为存储中的错误值
'


通过这种方式,每次提交时,您都不会看到最后一个
错误
,并且当您将
使用效果
视为一个在使用“副作用”(更改状态)作为
组件更新
时,也不需要比较
错误

,您需要注意
错误
消息
状态的变化

而不是

  // Similar to componentDidMount and componentDidUpdate
  //By running an empty array [] as a second argument,
  //we’re letting React know that the useEffect function doesn’t
  //depend on any values from props or state.
  useEffect(() => {
    const { error } = props;
    if (error !== form.error) {
      //check for register error
      if (error.id === "REGISTER_FAIL") {
        setValues({ msg: error.msg});
      } else {
        setValues({ msg: null });
      }
    }
  }, []);
你需要做什么

  useEffect(() => {
    const { error } = props;
    if (error !== form.error) {
      //check for register error
      if (error.id === "REGISTER_FAIL") {
-        setValues(({ msg: error.msg});
+       setValues({ ...form, msg: error.msg});
      } else {
-       setValues({ msg: null });
+       setValues({ ...form, msg: null });
      }
    }
  }, [error, form.msg]);
我之所以传播
…form
setValues({…form,msg:error.msg.msg})
是因为
React.useState
返回的更新程序函数(第二个参数)不会更新状态中的其他属性

So
setValues({msg:null})将从

{
  name: 'previous name',
  password: 'previous password',
  email: 'previous email',
  msg: 'previous message...'
}
进入
{msg:null}
删除
姓名、电子邮件、密码
属性

由于
React.useState
的更新程序(“别名”为
setState
in)和
setState
之间的行为不同,最终有人创建了它,除非绝对必要,否则您可能不应该使用它

旁注 与你的问题无关,你也可以 1.将
名称/电子邮件/密码/msg
分为不同的状态 2.或“使用钩子”

案例1的实施变化 如果要继续使用对象
表单
,可能需要遵循命名约定,将
setValues
更改为
setForm
const[formValues,setFormValues]=useState({…})

您可以更新每个字段,如

<TextField
  autoComplete="name"
  name="name"
  variant="outlined"
  required
  fullWidth
  id="name"
  label="Full Name"
  autoFocus
  value={name}
  onChange={e => setName(e.target.value)}
/>
setName(e.target.value)}
/>

您可以在此处使用for
onChange
onChange={useCallback(e=>setName(e.target.value),[name])}
,但除非您有性能问题,否则不必使用。一开始很简单,这应该是一个基于类的组件,在这里使用功能组件没有意义,IMHO.Hi@TobiasTengler。我可以问一下为什么功能组件(FC)在这里不起作用吗?我想知道为什么(不是想争论,只是想了解你的思维过程我从来没有说过它不起作用,只是基于类的组件对我个人来说更有意义。一般来说,功能组件应该是哑的,只呈现通过道具提供给它们的东西。那里有一堆处理程序,OP想添加更多的处理程序通过引入生命周期挂钩来增加复杂性。我想随着最近的更新,也许我只是在这方面过时了,谁知道呢,只是个人偏好。很抱歉,我误读了你之前的消息@TobiasTengler我理解你的观点,使用类组件更好,但我仍在尝试arn钩子使功能组件具有状态。另外,据我所知,material ui不支持类组件。感谢上面的代码。我使用上面的一些代码显示了消息。谢谢。这当然是一个很大的帮助和详细的解释。我将尝试案例#1,如果有任何问题,我将与您联系鱼钩。
{
  name: 'previous name',
  password: 'previous password',
  email: 'previous email',
  msg: 'previous message...'
}
const [name, setName] = useState('');
const [email, setEmail] = useState('');
const [password, setPassword] = useState('');
const [message, setMessage] = useState('');
<TextField
  autoComplete="name"
  name="name"
  variant="outlined"
  required
  fullWidth
  id="name"
  label="Full Name"
  autoFocus
  value={name}
  onChange={e => setName(e.target.value)}
/>