【问题标题】:SetState Not Working After GraphQL MutationGraphQL 突变后 SetState 不起作用
【发布时间】:2020-06-22 03:10:00
【问题描述】:

如果突变成功,我正在尝试将 ```submitForm()` 的 .then 中的 setAdded 转换为 true。如果这是真的,我想显示来自 SuccessMessage() 的消息。但是,当我记录添加的值时,我一直看到错误。

因为 added 没有更改为 true。突变成功时,我看不到任何消息。为什么不改?

export default function AddUserPage() {
  const [state, setState] = useState({
    firstName: '',
    lastName: '',
    email: '',
    password: '',
    phoneNumber:'',
    loggedIn: false,
  });  

  const [added, setAdded] = useState(false);

  function SuccessMessage(){
    if (added)
    {
      console.log('User Added');
      return (
      <Typography>
        User Added
        </Typography>)
    }
  }

  useEffect(() => {
    if(added){
      SuccessMessage();
    }
  },[] );

function submitForm(AddUserMutation: any) {
    const { firstName, lastName, email, password, phoneNumber } = state;
    if (firstName && lastName && email && password && phoneNumber) {
      AddUserMutation({
        variables: {
          firstName: firstName,
          lastName: lastName,
          email: email,
          password: password,
          phoneNumber: phoneNumber,
        },
      }).then(({ data }: any) => {
        setAdded(true);
        console.log('doing', added);
        console.log('ID: ', data.createUser.id);
        console.log('doing', added);
      })
        .catch(console.log)
    }
  }

  return (
    <Mutation mutation={AddUserMutation}>
      {(AddUserMutation: any) => (
        <div>
          <PermanentDrawerLeft></PermanentDrawerLeft>
          <Formik
            initialValues={{ firstName: '', lastName: '', email: '', password: '', phoneNumber: '' }}
            onSubmit={(values, actions) => {
              setTimeout(() => {
                alert(JSON.stringify(values, null, 2));
                actions.setSubmitting(false);
              }, 1000);
            }}
            validationSchema={schema}
          >
            {props => {
              const {
                values: { firstName, lastName, email, password, phoneNumber },
                errors,
                touched,
                handleChange,
                isValid,
                setFieldTouched
              } = props;
              const change = (name: string, e: any) => {
                e.persist();
                handleChange(e);
                setFieldTouched(name, true, false);
                setState( prevState  => ({ ...prevState,   [name]: e.target.value })); 
              };
              return (
                <div className='main-content'>
                  <form style={{ width: '100%' }} 
                  onSubmit={e => {e.preventDefault();
                    submitForm(AddUserMutation);SuccessMessage()}}>
                    <div>
                      <TextField
                        variant="outlined"
                        margin="normal"
                        id="firstName"
                        name="firstName"
                        helperText={touched.firstName ? errors.firstName : ""}
                        error={touched.firstName && Boolean(errors.firstName)}
                        label="First Name"
                        value={firstName}
                        onChange={change.bind(null, "firstName")}
                      />
                      <TextField
                        variant="outlined"
                        margin="normal"
                        id="email"
                        name="email"
                        helperText={touched.email ? errors.email : ""}
                        error={touched.email && Boolean(errors.email)}
                        label="Email"
                        value={email}
                        onChange={change.bind(null, "email")}
                      />
                      <Button
                      type="submit"
                      disabled={!isValid || !email || !password}
                      >
                        Add User</Button>
                    </div>
                  </form>
                </div>
              )
            }}
          </Formik>
        </div>
      )
      }
    </Mutation>
  );
}

【问题讨论】:

  • 如果你已经在使用钩子了,为什么不直接使用useMutation钩子呢?
  • 如果在 setAdded(true) 行之后添加一个 console.log() ,它会显示吗?
  • 实际上无法根据我的代码弄清楚如何使用它。你能帮忙吗? @trixn
  • 不,它不显示。一直说假的。这就是问题@rrd

标签: javascript reactjs typescript graphql react-hooks


【解决方案1】:

在调用setAdded 之后直接调用console.log() 将不会显示true,因为状态更新是异步的,并且只会在下一次渲染时可见。此外,您的 SuccessMessage 将永远不会被触发,因为您没有为您的 useEffect() 提供任何依赖项。这意味着它只会在挂载后被调用

需要将added添加到依赖列表中:

useEffect(() => {
    if(added){
        SuccessMessage();
    }
},[added]);

但实际上我看不出有任何理由在useEffect 中触发它。为什么不在突变处理程序中调用它?

如果你已经在使用钩子,你可以使用useMutation

您也不能从处理程序返回 JSX。它不会做任何事情。甚至知道在哪里显示您的&lt;Typography&gt;User Added&lt;/Typography&gt; 应该如何反应?您必须根据状态渲染组件本身的所有内容。

【讨论】:

  • 我这样做了。它现在将“用户添加”消息打印到控制台。来自 SuccessMessage() 函数,但仍不返回错误消息,即排版
  • @a125 这不是 react 的工作原理。您不能在处理程序中返回 JSX。应该如何反应甚至知道在哪里渲染这个?您要渲染的所有内容都必须由组件返回。通过更改将触发重新渲染的状态来更改渲染的内容。
  • 在表格末尾添加 {added &amp;&amp; SuccessMessage()} 有效。感谢您的帮助:)
【解决方案2】:

抱歉,但是...

...这看起来像是滥用反应的一个很好的例子...跳过基本教程、文档和混合随机的 oudated 示例的结果

  • useState(和setState)的异步性质——你不能指望更新的值;
  • 在不知道它如何影响行为的情况下使用 useEffect 参数;
  • 根本不需要'useEffect';
  • 从事件处理程序返回组件,而不是 [数据驱动] 条件渲染;
  • 如果使用了useMutation,则不需要将突变作为参数传递给事件处理程序;
  • 您正在使用 Formik(带有字段验证),然后在处理程序中检查参数(字段)是完全没有必要的;
  • 如果变量道具名称匹配,您可以简单地使用variables: { ...state }
  • Formik 管理值,您不需要使用本地状态来复制它 - 有什么理由吗?;
  • Formik 也有钩子 ;) 使用 useFormik();
  • ...事件处理程序、绑定...

【讨论】:

猜你喜欢
  • 2020-12-23
  • 2019-06-11
  • 2021-11-18
  • 2020-12-26
  • 2021-08-17
  • 1970-01-01
  • 2021-08-14
  • 2021-06-14
  • 1970-01-01
相关资源
最近更新 更多