首页 > 解决方案 > 通过观察状态变化来解决handleSubmit的promise

问题描述

我已经增强了 Context 的调度,类似于这篇博文中描述的内容。此外,就像 Redux 一样,我可以创建一个中间件链,我的所有操作都将贯穿它。基于来自 Real World Redux 的这个中间件示例,我有一个中间件可以集中处理所有 API 消耗。

这意味着我的组件调度操作来发起 API 请求,并且不能轻易地观察代表该异步操作的承诺。因此,我不能将该承诺传递给 RFF 的handleSubmit. 相反,我需要创建自己的异步函数来传递handleSubmit并通过观察应用程序状态的变化来解决它的承诺。

@erikras 创建了Redux Promise Listener,它使用中间件观察调度的动作来解决类似的问题。

我第一次创建了一个 React 钩子,它通过观察状态变化来解决 Promise,但感觉很尴尬:

/**
 * usePromiseSettler invokes an async executor function, and then will observe changes in
 * state to determine when the async function's promise has settled. Once settled,
 * either the success or failure callback will be invoked.
 *
 * @param executor Function that initiates state change we wish to observe
 * @param successCondition Condition that indicates executor operation succeeded
 * @param successCallback Callback to invoke when executor operation succeeds
 * @param failureCondition Condition that indicates executor operation has failed
 * @param failureCallback Callback to invoke when executor operation fails
 * @returns An async function returning a promise which will be settled when
 * a success or error condition is observed.
 */
export const usePromiseSettler = (
  executor: (...args: any[]) => any,
  successCondition: boolean,
  successCallback: (value?: any) => void,
  failureCondition: boolean,
  failureCallback: (value?: any) => void,
) => {
  const resolveRef = useRef<(value?: any) => void>();
  const successConditionRef = useRef<boolean>(false);
  const failureConditionRef = useRef<boolean>(false);

  const staticExecutor = React.useCallback(executor, []);

  const handlePromise = React.useCallback(
    (value) => {
      staticExecutor(value);
      return new Promise((resolve) => {
        resolveRef.current = resolve;
      });
    },
    [staticExecutor],
  );

  if (!successConditionRef.current && successCondition) {
    successCallback(resolveRef.current);
  }

  if (!failureConditionRef.current && failureCondition) {
    failureCallback(resolveRef.current);
  }

  successConditionRef.current = successCondition;
  failureConditionRef.current = failureCondition;

  return handlePromise;
};

用法:

const previousDidCreateSucceed = usePrevious(
    state.targetState.didCreateSucceed,
  );

const previousError = usePrevious(state.targetState.error);

const handleSubmit = usePromiseSettler(
    (target: TargetData) => {
      const action = requestPostTarget(target);
      dispatch(action);
    },
    !previousDidCreateSucceed && state.targetState.didCreateSucceed,
    (resolve) => {
      resolve(state.targetState.data);
      history.push("/targets");
    },
    !previousError && !!state.targetState.error,
    (resolve) => {
      resolve({ [FORM_ERROR]: state.targetState.error });
    },
  );

  ...
  return (
      <Form
        onSubmit={handleSubmit}

这个问题是否已经在其他地方以较低的复杂性解决了?

标签: react-final-formfinal-form

解决方案


推荐阅读