GraphQL突变后,SetState不起作用

时间:2020-03-10 08:33:20

标签: javascript reactjs typescript graphql react-hooks

如果突变成功,我将尝试在submitForm()的.then中从setAddedtrue。如果是这样,我想显示来自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>
  );
}

2 个答案:

答案 0 :(得分:1)

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

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

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

但是实际上我仍然没有理由在useEffect中触发它。为什么不只在变异处理程序中调用它呢?

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

此外,您不能从处理程序中返回JSX。它不会做任何事情。即使知道在何处显示<Typography>User Added</Typography>,也应该如何反应?您必须根据状态在组件本身中呈现所有内容。

答案 1 :(得分:0)

对不起,但是...

...看起来像是滥用行为的一个很好的例子...跳过了基础教程,文档并混合了随机的过时的例子

    useState(和setState)的
  • 异步性质-您不能期望更新的值;
  • 使用useEffect参数,却不知道它如何影响行为;
  • 根本不需要“ useEffect”;
  • 从事件处理程序中返回组件,而不是[数据驱动]条件渲染;
  • 如果使用useMutation,则无需将变异作为参数传递给事件处理程序;
  • 您正在使用Formik(具有字段验证),然后根本不需要检查处理程序中的params(字段);
  • 如果变量props名称匹配,则可以简单地使用variables: { ...state }
  • Formik管理值,您无需使用本地状态重复该操作-出于任何原因?;
  • Formik也有钩子;)使用useFormik();
  • ...事件处理程序,绑定...