更新两个 AsyncThunk 调用之间的 Redux 状态

问题描述 投票:0回答:1

我一直在研究一个涉及通过 asyncThunk 调用上传文件的调用的问题。调用完成后,它会返回文件路径的有效负载。

从那里,我尝试在 uploadFileAsyncThunk.fulfilled 时更新“addCase”代码块中名为“transaction”的对象的状态,以便可以将其保存在数据库中。一切都按其应有的方式运行,除了代码执行的顺序不是我期望的那样。当事务对象发送到第二个 asyncThunk (postTransactionThunk) 时,状态似乎没有更新。

通过代码调试,我可以看到 uploadResultAction 填充了我期望的返回数据。并且

uploadFileThunk.fulfilled.match(uploadResultAction)
对于继续执行代码的其余部分是有效的。从那里,获取 filePathParam 确实包含我想要的数据,并且分派数据确实有效。我可以在组件顶部控制台记录我的数据已更新。然而,当我通过 Redux DevTools 查看状态时。我的状态在
dispatchPostTransactionThunk
执行之前不会更新,此时为时已晚,因为 POST 引用的事务数据已过时。

如何更新我的

transaction
状态,以便能够使用最新数据执行 postTransactionThunk?

const MyComponent = () => {

    const transaction = useAppSelector(
        (state) => state.transaction.transaction
    );

    const handleClick = async (e) => {
        e.preventDefault();

        // returned value is accurate
        const uploadResultAction = await  dispatch(uploadFileThunk(file));

       // condition passes and enters code block
        if (uploadFileThunk.fulfilled.match(uploadResultAction)) {
            // filePathParam has the payload I want.
            const filePathParam = 
            {
                filePath: uploadResultAction.payload.response,
            };
            // dispatch executes updating transaction.filePath.
            dispatch(updateTransaction(filePathParam));

            // ISSUE: transaction does not have the transaction.filePath updated; filePath is still an empty string.
            const postTransactionResultAction = await dispatch(postTransactionThunk(transaction));
        
            if (postTransactionThunk.fulfilled.match(
                postTransactionResultAction)) {
                    // ... 
                }
        }

    }
    return (
        <div>
            <Button onClick={handleSubmit}>Click</Button>
        </div>
    );

}

export default MyComponent;

以下是完成交易后更新交易的补充逻辑:

const initialTransactionState = {
    filePath: '',
};

const initialState = {
    transaction: initialTransactionState,
    fileUploadResponse: null,
    loading: false,
    error: null,
};

export const postTransactionThunk = createAsyncThunk(
    'postTransactionThunk',
    async (transaction, { dispatch }) => {
        const response = await dispatch(
            transactionApiSlice.endpoints.postTransaction.initiate(transaction)
        );
        return response.data;
    }
);

export const uploadFileThunk = createAsyncThunk(
    'uploadFileThunk',
    async (file, { dispatch }) => {
        const response = await dispatch(
            fileApiSlice.endpoints.postFile.initiate(file)
        );
        return response.data;
    }
);

export const transactionSlice = createSlice({
    name: 'transaction',
    initialState,
    reducers: {
        updateTransaction: (state, action) => {
            return {
                ...state,
                transaction: { ...state.transaction, ...action.payload },
            };
        },
    },
    extraReducers: (builder) => {
        builder
            .addCase(uploadFileThunk.fulfilled, (state, action) => {
                return {
                    ...state,
                    loading: false,
                    error: null,
                    fileUploadResponse: action.payload,
                    transaction: {
                        ...state.transaction,
                        filePath: action.payload.response,
                    },
                };
            })
    },
});

export const {
    updateTransaction,
} = transactionSlice.actions;

export default transactionSlice.reducer;

我尝试过通过代码进行调试。我还尝试在每个调度调用之间放置级联 .then(...) 块,这也没有什么区别。

reactjs redux
1个回答
0
投票

问题似乎是由

transaction
操作中流更新并传递给
updateTransaction
postTransactionThunk
值的陈旧闭包。

我建议更新

postTransactionThunk
以直接访问当前状态值,而不是依赖于可能已过时的传递值。在 thunk 中,您可以使用
thunkApi.getState
访问 current 状态值

export const postTransactionThunk = createAsyncThunk(
  'postTransactionThunk',
  async (_, { dispatch, getState }) => {
    const state = getState();
    const transaction = state.transaction.transaction;

    const { data } = await dispatch(
      transactionApiSlice
        .endpoints
        .postTransaction
        .initiate(transaction)
      ).unwrap();

    return data;
  }
);

UI 代码不需要具有当前

transaction
状态,请使用
dispatch(postTransactionThunk())

const uploadResultAction = await dispatch(uploadFileThunk(file));

if (uploadFileThunk.fulfilled.match(uploadResultAction)) {
  const filePathParam = {
    filePath: uploadResultAction.payload.response,
  };
  dispatch(updateTransaction(filePathParam));

  const postTransactionResultAction = await dispatch(postTransactionThunk());

  if (
    postTransactionThunk.fulfilled.match(postTransactionResultAction)
  ) {
    // ... 
  }
}

我建议也充分发挥 Thunk 的潜力。您可以等待并解开 thunk 结果,而不是在本地使用匹配器。类似于以下内容:

try {
  const { response: filePath } = await dispatch(uploadFileThunk(file)).unwrap();

  const filePathParam = { filePath };
  dispatch(updateTransaction(filePathParam));

  await dispatch(postTransactionThunk()).unwrap();

  // ... postTransactionThunk success, keep going
} catch(error) {
  // rejected Promise, thrown error, postTransactionThunk failure
}
最新问题
© www.soinside.com 2019 - 2025. All rights reserved.