Замените <Formik>на использование Formik - PullRequest
0 голосов
/ 28 марта 2020

Я использую Formik / Yup для проверки страницы, которая вызывает мутацию GraphQL. Мой код работает полностью:

export default function RemoveUserPage() {
  const [isSubmitted, setIsSubmitted] = useState(false);
  const [isRemoved ,setIsRemoved] = useState(false);
  const [errorMessage, setErrorMessage] = useState('');

  const [removeUser] = useMutation(RemoveUserMutation);

  function submitForm(email: string) {
    setIsSubmitted(true);
    removeUser({
        variables: {
            email: email,
        },
    }).then(({ data }: any) => {
      setIsRemoved(true);
      console.log('info: ', data.deleteUser);
    })
    .catch((error: { message: string; }) => {
      setIsRemoved(false);
      console.log("Error msg:" + error.message);
      setErrorMessage(error.message)
    })
  }

  return (
    <div>
      <PermanentDrawerLeft></PermanentDrawerLeft>
      <Formik
        initialValues={{ email: '' }}
        onSubmit={(values, actions) => {
          setTimeout(() => {
            alert(JSON.stringify(values, null, 2));
            actions.setSubmitting(false);
          }, 1000);
        }}
        validationSchema={schema}
      >
        {props => {
          const {
            values: { email },
            errors,
            touched,
            handleChange,
            isValid,
            setFieldTouched
          } = props;
          const change = (name: string, e: any) => {
            e.persist();
            handleChange(e);
            setFieldTouched(name, true, false);           
          };
          return (
            <div className='main-content'>
              <form style={{ width: '100%' }}
               onSubmit={e => {e.preventDefault();submitForm(email)
                }}>
                <div>
                  <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")}
                  />
                  <br></br>
                  <Button
                  type="submit"
                  disabled={!isValid || !email}
                  >
                    Remove User</Button>
                </div>
              </form>
              <br></br>
              {isSubmitted && StatusMessage(isRemoved, errorMessage)}
            </div>
          )
        }}
      </Formik>
    </div>
  );
}

Однако теперь я хочу использовать useFormik hook вместо <Formik>, и я не могу это сделать. Я видел следующий пример, но я просто не могу понять, как именно я мог бы использовать его синтаксически в моем случае, так как я использую компоненты пользовательского интерфейса вместо входов formi c -specifi c.

https://jaredpalmer.com/formik/docs/api/useFormik

Редактировать:

Это компилируется и все, но в текстовых полях проверки не происходит. Чего мне не хватает?

export const schema = Yup.object({
  email: Yup.string()
    .email('Invalid Email')
    .required('This Field is Required'),
});


export default function RemoveUserPage() {
  const [isSubmitted, setIsSubmitted] = useState(false);
  const [isRemoved, setIsRemoved] = useState(false);
  const [errorMessage, setErrorMessage] = useState('');

  const [removeUser] = useMutation<DeleteUserResponse>(REMOVE_USER);

  let submitForm = (email: string) => {
    setIsSubmitted(true);
    removeUser({
      variables: {
        email: email,
      },
    })
      .then(({ data }: ExecutionResult<DeleteUserResponse>) => {
        if (data !== null && data !== undefined) {
          setIsRemoved(true);
          console.log('info: ', data.deleteUser);
        }
      })
      .catch((error: { message: string }) => {
        setIsRemoved(false);
        console.log('Error msg:' + error.message);
        setErrorMessage(error.message);
      });
  };

  const formik = useFormik({
    initialValues:{ email: '' },
    onSubmit:(values, actions) => {
       setTimeout(() => {
          alert(JSON.stringify(values, null, 2));
          actions.setSubmitting(false);
          }, 1000);
        },
       validationSchema:{schema}
    })

    const handleChange = (e: ChangeEvent<HTMLInputElement>)=>{
      const {name,value} = e.target;
      formik.setFieldValue(name,value);
     }

  return (
    <div>
      <PermanentDrawerLeft></PermanentDrawerLeft>
            <Wrapper>
              <Form
                onSubmit={e => {
                  e.preventDefault();
                  submitForm(formik.values.email);
                }}>
                <div>
                  <TextField
                    variant="outlined"
                    margin="normal"
                    id="email"
                    name="email"
                    helperText={formik.touched.email ? formik.errors.email : ''}
                    error={formik.touched.email && Boolean(formik.errors.email)}
                    label="Email"
                    value={formik.values.email}
                    //onChange={change.bind(null, 'email')}
                    onChange={handleChange}
                  />
                  <br></br>
                  <CustomButton
                    disabled={!formik.values.email}
                    text={'Remove User'}
                  />
                </div>
              </Form>
              <br></br>
              {isSubmitted && StatusMessage(isRemoved, errorMessage)}
              </Wrapper>
    </div>
  );
}

Это дало мне эту ошибку:

TypeError: schema[sync ? 'validateSync' : 'validate'] is not a function. (In 'schema[sync ? 'validateSync' : 'validate'](validateData, {
    abortEarly: false,
    context: context
  })', 'schema[sync ? 'validateSync' : 'validate']' is undefined)

Во-вторых, раньше я использовал isValid для кнопки, но теперь она выдает ошибку. Есть ли альтернатива?

1 Ответ

0 голосов
/ 01 апреля 2020

Как уже упоминал Джоу Хокинс, будет очень сложно узнать о хуках, но я предоставлю вам некоторые изменения и ответ, чтобы помочь вам начать.

export default function RemoveUserPage() {
  const [isSubmitted, setIsSubmitted] = useState(false);
  const [isRemoved ,setIsRemoved] = useState(false);
  const [errorMessage, setErrorMessage] = useState('');

  const [removeUser] = useMutation(RemoveUserMutation);

  function submitForm(email: string) {
    setIsSubmitted(true);
    removeUser({
        variables: {
            email: email,
        },
    }).then(({ data }: any) => {
      setIsRemoved(true);
      console.log('info: ', data.deleteUser);
    })
    .catch((error: { message: string; }) => {
      setIsRemoved(false);
      console.log("Error msg:" + error.message);
      setErrorMessage(error.message)
    })
  }

const formik = useFormik({
initialValues:{ email: '' },
onSubmit:(values, actions) => {
   setTimeout(() => {
      alert(JSON.stringify(values, null, 2));
      actions.setSubmitting(false);
      }, 1000);
    },
   validationSchema:schema
})

// depend on the return value
const handleSubmit = (someReturnValue or event)=>{
// if the return event has name
// such as event.target.name then you got the name
// and try event.target.value 
// then set field value

// eg: const value = event.current.value

formik.setFieldValue(name, value)
}

// dont forget to set onBlur as well
// this i will leave it to you

  return (
    <div>
      <PermanentDrawerLeft></PermanentDrawerLeft>

            <div className='main-content'>
              <form style={{ width: '100%' }}
               onSubmit={formik.handleSubmit}>
                <div>
                  <TextField
                    variant="outlined"
                    margin="normal"
                    id="email"
                    name="email"
                    helperText={formik.touched.email ? formik.errors.email : ""}
                    error={formik.touched.email && Boolean(formik.errors.email)}
                    label="Email"
                    value={formik.values.email}
                    onChange={handleChange}
                  />
                  <br></br>
                  <Button
                  type="submit"
                  disabled={!isValid || !email}
                  >
                    Remove User</Button>
                </div>
              </form>
              <br></br>
              {isSubmitted && StatusMessage(isRemoved, errorMessage)}
            </div>
    </div>
  );
}

Редактировать: Поскольку вы используете текстовое поле Material Ui добавьте handleChange метод

const handleChange = (event)=>{
 // get name and value from event.target
 // is the same as const name = event.target.name
 const {name,value} = event.target
 // make sure you have name prop in 
 // your textfield and it is same name as your initial state
 formik.setFieldValue(name,value) // this call formik to set your value
}

, а затем в свой компонент электронной почты onChange={handleChange}

...