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

Javascript 在Redux中将异步与同步操作链接以计算初始状态?,javascript,redux,react-redux,redux-thunk,Javascript,Redux,React Redux,Redux Thunk,对不起,我的短信太长了。。。 我试图找出最好的方法来链接一些需要等待对方计算初始状态的操作。重新选择可能会有所帮助,但我很难找到合适的方法。 我使用的是ImmutableJS,但我将使用标准JSON来描述我的问题。初始状态应类似于: { "book": { "id": 1, "title": "THE book", "notes": [ 1, 2, 4 ] }, "detailedNotes": [ { "id": 1, "text": "Just a note",

对不起,我的短信太长了。。。 我试图找出最好的方法来链接一些需要等待对方计算初始状态的操作。重新选择可能会有所帮助,但我很难找到合适的方法。 我使用的是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"
}
bookdetailed notes来自GET调用(使用fetch)notesByCategory由我的代码计算(此时在reducer中…),我还需要将activeCategory的初始值设置为第一个计算的类别(在示例中至关重要)。 下面是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
        }
    }
还有减速机的组成,我省略了。
现在,我想将初始的activeCategory设置为第一个类别,但我有一个问题,我不知道该放在哪里。我必须先等待以计算状态的notesByCategory部分。我觉得这个计算不应该在减速机里。有什么建议吗?

通常,默认状态应由还原程序处理。在开始时,在减速器中得到null状态,并且应该提供一些“初始”状态


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

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

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

选择器可以访问整个存储区,因此在返回activeCategory的选择器中,您可以使用一些逻辑返回存储区中的
activeCategory
(如果不是
null
),或者基于可用类别返回一些默认值(如果
null


将您的存储视为“真理之源”,并使用选择器从中导出您需要的所有内容,这有助于防止不一致,因为您可以确信存储是正确的,并且独立于其他数据。

好吧,正如您在代码示例中所看到的,我的所有还原器中都有默认参数。问题是我需要计算状态(可能会将计算出的状态存储在存储中),基本上是一个连接。我可以在reducer中计算状态,实际上我现在正在这样做。您可以轻松地在reducer中进行一些简单的同步状态计算(如果传入状态为null,则将其视为初始状态)。然而,从您的描述中,它开始觉得您应该将计算移到其他地方,例如,移动到action creator或某个app init块。您是对的,目前我正在使用一个选择器,该选择器将此连接起来(无法告诉我为什么在阅读有关Redux的内容时忽略了这些选择器…),这很有意义。由于某种原因,我在阅读Redux时错过了选择器。实际上,我删除了notesByCategory计算,并在reducer中为其添加了一个选择器(尽管它可能位于我猜想的任何地方)。不确定在这种情况下使用重新选择的好处是什么..嘿,Drew,实际上我还有一个问题。activeCategory的初始值为null,因为尚未处理按类别连接notes。作为一种解决方法,我使用componentWillReceiveProps等待处理notesByCategory选择器并填充相应的props。有点棘手和难看?当您开始将大量逻辑移到选择器时,重新选择(或类似的操作)就变得非常必要,并且它们的计算成本变得有些高。使用Redux,如果您的计算所依赖的数据没有更改,则每一个操作都将触发重新计算,这通常是不必要的。“重新选择”只会记忆最后一个输入集,以避免重新计算。@vicusbass不确定我是否理解这里的内容,但在选择器和/或组件中,当
activeCategory
null
detailedNotes
为空时,您应该说明代码路径。最初
activeCategory
为null,
detailedNotes
为空。然后,容器将发送一个对
detailedNotes
的请求,并在收到数据时使用基本操作填充状态。根据你的建议,我使用选择器来按类别加入注释。问题是,我想将选择器中的第一个类别设置为
activeCategory
,但我不知道根据选择器结果将
setActiveCategory
值分派到哪里是最佳位置,因此我在
componentWillReceiveProps
中执行此操作(因为选择器在容器中用作道具)。糟糕?