繁体   English   中英

GraphQL 突变后 SetState 不起作用

[英]SetState Not Working After GraphQL Mutation

如果突变成功,我会尝试在 ```submitForm()`` 的setAddedtrue 如果这是真的,我想显示来自SuccessfulMessage() 的消息。 但是,当我记录 added 的值时,我一直看到错误。

由于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>
  );
}

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

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

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

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

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

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

对不起,可是 ...

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

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM