React表单提交正在触发重新呈现(尽管e.preventDefault)

时间:2019-07-23 23:26:22

标签: javascript reactjs react-hooks

我刚刚重组了授权表单组件,以将状态处理逻辑拉到一个自定义钩子中,以便可以在其他地方重用它。在此之前,提交我的表单不会触发重新呈现(例如,如果存在验证错误),但是现在可以。需要说明的是,页面实际上并没有重新加载/刷新(因此我认为这不是来自默认的表单提交行为),但是背景图像(来自更高级别的容器组件)确实可以重新渲染。

AuthForm.js

const AuthForm = ({ buttonText, formType, onAuth, history, ...props }) => {

  const submitData = () => {
    onAuth(formType, values, history);
  }

  const {
    values,
    errors,
    handleChange,
    handleSubmit,
  } = useForm(submitData, validate);

return (
    <Form onSubmit={handleSubmit}>
      <FlexContainer flexDirection="column" justify="space-between" >
        <FlexContainer flexDirection="column" >
          <TextInput
            id="email"
            name="email"
            onChange={handleChange}
            value={values.email || ''}
            placeholder="Email"
            onFocus={(e) => e.target.placeholder = ""}
            onBlur={(e) => e.target.placeholder = "Email"}
          />
          {errors.email && <ErrorMessage>{errors.email}</ErrorMessage>}
          <TextInput
            id="password"
            name="password"
            onChange={handleChange}
            type="password"
            value={values.password || ''}
            placeholder="Password"
            onFocus={(e) => e.target.placeholder = ""}
            onBlur={(e) => e.target.placeholder = "Password"}
          />
          {errors.password && <ErrorMessage>{errors.password}</ErrorMessage>}
        </FlexContainer>
        <FlexContainer flexDirection='column' >
          <Button type="submit" buttonText={buttonText} buttonSize="large"/>
        </FlexContainer>
      </FlexContainer>
    </Form>
  )
};
...
function validate(values) {
  let errors = {};
  if (!values.email) {
    errors.email = 'Email address is required';
  } else if (!/^([a-zA-Z0-9_\-\.]+)@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.)|(([a-zA-Z0-9\-]+\.)+))([a-zA-Z]{2,4}|[0-9]{1,3})(\]?)$/.test(values.email)) {
    errors.email = 'Email address is invalid';
  }
  if (!values.password) {
    errors.password = 'Password is required';
  } else if (values.password.length < 8) {
    errors.password = 'Password must be 8 or more characters';
  }
  return errors;
};

export default AuthForm;

useForm.js(自定义钩子)-取自this article

的修改
const useForm = (callback, validate) => {

  const [values, setValues] = useState({});
  const [errors, setErrors] = useState({});
  const [isSubmitting, setIsSubmitting] = useState(false);

  useEffect(() => {
    if (Object.keys(errors).length === 0 && isSubmitting) {
      callback();
    }
    else if (isSubmitting) {
      setValues({});
    }
  }, [errors]);

  const handleSubmit = (e) => {
    e.preventDefault();
    setErrors(validate(values));
    setIsSubmitting(true);
  };

  const handleChange = (event) => {
    event.persist();
    setValues(values => ({ ...values, [event.target.name]: event.target.value }));
  };

  return {
    handleChange,
    handleSubmit,
    values,
    errors,
  }
};

export default useForm;

鉴于大多数代码是相同的(只是重新定位到了一个钩子),我不知道为什么它会导致在树的上方重新渲染。

AuthForm由AuthContainer呈现,而AuthContainer由AuthPage呈现。 AuthPage是渲染我的背景图像的地方。

AuthPage.js

const Background = styled.div`
  background-image: url('myimage.jpg');
  background-repeat: no-repeat;
  background-size: cover;
  min-height: 90vh;
`

const AuthPage = (props) => (

  <Background>
    <FlexContainer justify="space-evenly" padding="100px 40px 0 40px" wrap="nowrap">
      <AuthContainer {...props}/>
      <AsideContainer {...props} />
    </FlexContainer>
  </Background>
)

export default AuthPage;

0 个答案:

没有答案