我已经增强了 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}
这个问题是否已经在其他地方以较低的复杂性解决了?