Reactjs 等待异步提交表单分派完成,然后继续下一行

Reactjs 等待异步提交表单分派完成,然后继续下一行,reactjs,react-native,redux,react-redux,react-navigation,Reactjs,React Native,Redux,React Redux,React Navigation,我有一个登录表单,我想处理它的提交功能,并通过redux更新处理 Login.js: const Login = (props) => { const dispatch = useDispatch(); const isUserExists = useSelector((state) => state.auth.isUserExists); const handleSubmitForm = (vals) => { dispatch(isUserExists

我有一个登录表单,我想处理它的提交功能,并通过redux更新处理

Login.js:

const Login = (props) => {
  const dispatch = useDispatch();
  const isUserExists = useSelector((state) => state.auth.isUserExists);

  const handleSubmitForm = (vals) => {
    dispatch(isUserExistsByPhoneNumber("Login", vals)).then(() =>
      props.navigation.navigate(isUserExists ? "VerifyAuth" : "Signup", {
        vals: vals,
        sentFrom: "Login",
      })
    );
  };

const LoginForm = (props) => {
  const handleFormSubmit = () => {
    props.submitForm(values);
  };

  const [values, handleChange, handleSubmit] = useForm(handleFormSubmit);

  return (
    <View>
      <Input
        name="phoneNumber"
        value={values.phoneNumber || ""}
        onChange={(name, value) => handleChange(name, value)}
        label="Phone Number"
        keyboardType="number-pad"
      />

      <Button
        mode="outlined"
        onPress={handleSubmit}
        loading={props.submitting}
        disabled={props.submitting}>
        Login
      </Button>
    </View>
  );
};
export const isUserExistsByPhoneNumber = (sentFrom, phoneNumber) => {
  return (dispatch) => {
    dispatch({ type: authTypes.GET_IS_USER_EXISTS_REQUEST });
    return authService
      .checkIfUserExists(sentFrom, phoneNumber)
      .then((response) => {
        dispatch({ type: authTypes.GET_IS_USER_EXISTS_SUCCESS });
        dispatch(setIsUserExists(response));
      })
      .catch((errors) => {
        dispatch({ type: authTypes.GET_IS_USER_EXISTS_ERROR, payload: errors });
      });
  };
};
LoginForm.js:

const Login = (props) => {
  const dispatch = useDispatch();
  const isUserExists = useSelector((state) => state.auth.isUserExists);

  const handleSubmitForm = (vals) => {
    dispatch(isUserExistsByPhoneNumber("Login", vals)).then(() =>
      props.navigation.navigate(isUserExists ? "VerifyAuth" : "Signup", {
        vals: vals,
        sentFrom: "Login",
      })
    );
  };

const LoginForm = (props) => {
  const handleFormSubmit = () => {
    props.submitForm(values);
  };

  const [values, handleChange, handleSubmit] = useForm(handleFormSubmit);

  return (
    <View>
      <Input
        name="phoneNumber"
        value={values.phoneNumber || ""}
        onChange={(name, value) => handleChange(name, value)}
        label="Phone Number"
        keyboardType="number-pad"
      />

      <Button
        mode="outlined"
        onPress={handleSubmit}
        loading={props.submitting}
        disabled={props.submitting}>
        Login
      </Button>
    </View>
  );
};
export const isUserExistsByPhoneNumber = (sentFrom, phoneNumber) => {
  return (dispatch) => {
    dispatch({ type: authTypes.GET_IS_USER_EXISTS_REQUEST });
    return authService
      .checkIfUserExists(sentFrom, phoneNumber)
      .then((response) => {
        dispatch({ type: authTypes.GET_IS_USER_EXISTS_SUCCESS });
        dispatch(setIsUserExists(response));
      })
      .catch((errors) => {
        dispatch({ type: authTypes.GET_IS_USER_EXISTS_ERROR, payload: errors });
      });
  };
};
代码不起作用,原因很简单,因为在
Login.js
上分派后的“.then”没有等待分派完成,然后再继续

如何修复此问题,并仅在分派完成后读取isUserExists数据

如果我使用useEffect,我是否需要创建“isDoneDispatching”道具并仅在该道具更新时导航


谢谢。

将导航移动到
useffect
时,您的思路是正确的

但是您似乎没有在redux存储中存储

因此,您必须将它们存储在组件状态中,以便将它们传递给导航逻辑

const Login = (props) => {
  const dispatch = useDispatch();
  const isUserExists = useSelector((state) => state.auth.isUserExists);

  // store values in component state
  const [values, setValues] = useState(null);
  const [allowNavigate, setAllowNavigate] = useState(false);

  const handleSubmitForm = (vals) => {
    // store values in component state since you do not store them in redux state
    setValues(vals);

    dispatch(isUserExistsByPhoneNumber("Login", vals)).then(() => {
      setAllowNavigate(true);
    });
  };

  useEffect(() => {
    if (allowNavigate) {
      props.navigation.navigate(isUserExists ? "VerifyAuth" : "Signup", {
        vals: values,
        sentFrom: "Login",
      });
    }
  }, [allowNavigate, isUserExists, values]); // track values and isUserExists change

  // ...
};

将导航移动到
useffect
时,您的思路是正确的

但是您似乎没有在redux存储中存储

因此,您必须将它们存储在组件状态中,以便将它们传递给导航逻辑

const Login = (props) => {
  const dispatch = useDispatch();
  const isUserExists = useSelector((state) => state.auth.isUserExists);

  // store values in component state
  const [values, setValues] = useState(null);
  const [allowNavigate, setAllowNavigate] = useState(false);

  const handleSubmitForm = (vals) => {
    // store values in component state since you do not store them in redux state
    setValues(vals);

    dispatch(isUserExistsByPhoneNumber("Login", vals)).then(() => {
      setAllowNavigate(true);
    });
  };

  useEffect(() => {
    if (allowNavigate) {
      props.navigation.navigate(isUserExists ? "VerifyAuth" : "Signup", {
        vals: values,
        sentFrom: "Login",
      });
    }
  }, [allowNavigate, isUserExists, values]); // track values and isUserExists change

  // ...
};

我是否需要将isUserExists的默认val设置为null,并检查内部useEffect是否为null?否则,在调度结束之前,useEffect将在第一次渲染时运行,这仍然无法修复错误。你是对的,这样它将在第一次渲染时重定向,我的错误。。。在这种情况下,我希望明确我的意图,并添加一个单独的状态来跟踪这一点。请参阅更新的unswerExists。我是否需要将isUserExists的默认值设置为null,并检查内部useEffect是否为null?否则,在调度结束之前,useEffect将在第一次渲染时运行,这仍然无法修复错误。你是对的,这样它将在第一次渲染时重定向,我的错误。。。在这种情况下,我希望明确我的意图,并添加一个单独的状态来跟踪这一点。请参阅更新的unswer