在 Redux 中将异步与同步操作链接起来以计算初始状态?

Chaining async with sync actions in Redux for calculating initial state?

抱歉,文字太长了... 我试图找出最好的方法来链接一些需要等待彼此来计算初始状态的动作。可能 reselect 会有所帮助,但我很难弄清楚如何适应它。 我正在使用 ImmutableJS,但我将使用标准 JSON 来描述我的麻烦。初始状态应该是这样的:

{
"book": {
"id": 1,
"title": "THE book",
"notes": [
  1,
  2,
  4
]
 },
 "detailedNotes": [
{
  "id": 1,
  "text": "Just a note",
  "categories": [
    "Vital"
  ]
},
{
  "id": 2,
  "text": "Testing",
  "categories": [
    "Vital"
  ]
},
{
  "id": 4,
  "text": "Doodling",
  "categories": [
    "Relevant"
  ]
}
],
"notesByCategory": [
{
  "Vital": [
    1,
    2
   ]
 },
 {
  "Relevant": [
    4
  ]
 }
 ],
 "activeCategory": "Vital"
}

bookdetailedNotes 来自 GET 调用(使用提取)。 notesByCategory 由我的代码计算(目前在减速器中......)我还需要将 activeCategory 的初始值设置为首先计算类别(示例中的 Vital)。 这是 actions.js 和 reducer.js 相关代码:

        //in actions
    export function fetchBook(id) {
        return function (dispatch) {
            return fetch('/api/book/' + id)
                .then(json => {
                        dispatch(receiveBook(json));
                        dispatch(fetchDetailedNotes(json['notes']));
                    }
                );
        }
    }
    export function fetchDetailedNotes(ids) {
        return function (dispatch) {
            return fetch('/api/notes/?ids=' + ids.join())
                .then(json => dispatch(receiveDetailedNotes(json)))
        }
    }
    export function receiveDetailedNotes(detailedNotes) {
        return {
            type: RECEIVE_DETAILED_Notes,
            detailedNotes
        }
    }

    //in reducer
    function detailedNotesReducer(state = List(), action) {
        switch (action.type) {
            case actions.RECEIVE_DETAILED_NOTES:
                return fromJS(action.detailedNotes);
            default:
                return state
        }
    }
    function notesByCategory(state = List(), action) {
        switch (action.type) {
            case actions.RECEIVE_DETAILED_NOTES:
                return extractNotesByCategory(state, action.detailedNotes);
            default:
                return state
        }
    }

还有reducer组成,我省略了。 现在,我想将初始 activeCategory 设置为第一个类别,但我有一个问题,我不知道该把它放在哪里。我必须先等待计算状态的 notesByCategory 部分。我觉得这个计算不应该在reducer里面。有什么建议吗?

通常,默认状态应由您的减速器处理。一开始你在你的减速器中得到空状态,你应该提供一些 'initial' 状态。

在您的情况下,这通常使用默认参数 (=List()) 的便捷语法。

您可以通过不在您的状态中存储派生数据来避免这种情况,而是使用选择器来计算它(尽管您不必为此使用重新选择)。

选择器实际上只是一个函数,它接受通过 mapStateToProps 传入的状态,并派生出容器组件作为 props 获得的内容。

您的选择器可以访问整个商店,因此在 returns activeCategory 的选择器中,您可以有一些逻辑 return activeCategory(如果不是 null) 在商店或一些基于可用类别的默认值(如果 null)。

将您的商店视为 'source of truth' 并使用选择器从那里获取您需要的一切具有防止不一致的额外好处,因为您可以确信商店是正确的并且独立于其他数据。