首页 > 解决方案 > forEach - 在 Redux 中向 action.data 添加键/值 - console.log 有效,但 Redux 状态未更新

问题描述

在异步 Redux 操作中,我使用 graphQL 收集一些数据,然后调用另一个异步操作,该操作在对象中循环(使用 forEach)并添加一些键。

UserTopicActions.js


export const sendGetUserTopicSuccess = data => ({
    type: action_types.SEND_GET_USER_TOPIC_SUCCESS,
    data
});
 ...

export function sendGetUserTopic(user_id, nextToken = null) {
    return async (dispatch) => {
        dispatch(sendGetUserTopicBegin());
        ...
        try {
            const data = await API.graphql(graphqlOperation(gqlUserTopic.getUserTopic, variables))
            data_uri = await getCarouselImgUri(data.data.getUserTopic)
            dispatch(sendGetUserTopicSuccess(data_uri));

        } catch (err) {
            dispatch(sendGetUserTopicFailure(err));
        }
    };
}

amplifyAsync.js

import { Storage } from 'aws-amplify';

export default async function getCarouselImgUri(raw_data) {
    data = JSON.parse(raw_data.data)
    topics = data.topics
    // Fetching thumbnails for cards
    let card_img_uri
    topics.forEach((topic) => {
        topic['subtopics'].forEach(async (subtopic) => {
            card_img_uri = 'topic/' + topic.id + '/' + subtopic.id + '/' + 'thumbnail.jpg'
            subtopic['uri'] = await Storage.get(card_img_uri)      <------------ New Key!
        })
    })
    console.log(topics)
    return topics

}

UserTopicReducer.js

export default (state = initialState, action) => {
    switch (action.type) {
        case SEND_GET_USER_TOPIC_BEGIN:
            return {
                ...state,
                isGettingUserTopic: true,
            };
        case SEND_GET_USER_TOPIC_SUCCESS:
            console.log(action.data)
            return {
                ...state,
                isGettingUserTopic: false,
                topics: action.data
            };
    ...

如果我在 reducer 中控制台记录 action.data,我会看到新键。另一方面,在状态和分派的SEND_GET_USER_TOPIC_SUCCESS动作中,新键不存在。

为什么?如何在 Redux 异步操作的数据中添加新键?

标签: javascriptreactjsreduxforeach

解决方案


经过几个痛苦的小时后,我发现了错误:

In amplifyAsync.js: Async ... wait不能保证里面的所有承诺forEach()都得到解决。

我认为最好的解决方案是将所有承诺放在一个数组中,然后使用 promise.all,但由于我想保持相同的字典结构(并且 promise.all 不适用于字典),所以我暂时使用了普通的外观和异步等待。这样,所有请求都按顺序完成。这是一个非优化的解决方案,但现在它可以工作。

在调试 Promise 时,请确保您不这样做,console.log(JSON.stringify(data))否则标准console.log(data)可能会打印已解决的 Promise 的值,该值在执行时可能不可用。


推荐阅读