不影响状态的 Redux 应用程序业务逻辑?

Redux app business logic that doesn't affect the state?

我有一个应用程序利用 Oauth2 "redirect flow" 来验证用户,即用户被重定向到另一个网站登录,然后被重定向回我的网站。

文档和其他来源似乎都声称业务逻辑应该放在 action creator 或 reducer 中。但是我有一个 login() 函数,它不会以任何方式改变状态,它所做的是将应用程序的当前状态保存为 localStorage 中的普通对象,然后将用户重定向到授权服务器。当用户登录并被重定向回来时,状态被恢复(通过另一段代码)并作为初始状态提供给我的商店创建者功能。

我的问题:login 函数的逻辑只是检索状态但不会以任何方式更改它,因此它不属于减速器。它也没有 return 动作创建者定义的动作。我应该把它放在我的应用程序结构中的什么位置?

是否"ok" 有一个实际上不创建动作的动作创建者?我现在正在用 redux-thunk 做这个(因为我需要 getState()),它没有任何问题,但感觉不对,因为它实际上不是 "action creator",另一方面我也有一个 logout() 功能可以执行 return 一个动作,所以感觉他们应该住在同一个地方。我想这是一种极端情况,但不是真的,因为我能想到很多理由以这种方式保存状态并将访问者重定向到其他站点(或者甚至只是保存状态而不重定向)。

PS。我知道有一些库可以自动将我的 redux 存储与 localStorage 同步,但这并不是问题的重点。

编辑:一些说明:

来自 Redux docs 关于放置业务逻辑的位置: 对于究竟哪些逻辑应该放在 reducer 或 action creator 中,没有一个明确的答案。

继续阅读,很明显只有两个地方我应该放置业务逻辑,要么在 reducer 中,要么在 action creator 中。现在,由于我想做的事情不会影响状态,而根据定义,reducer 会影响状态,所以我倾向于将此逻辑放在 action creator 中。

关于动作创建器的文档:动作创建器就是创建动作的函数。将术语“动作”和“动作创建者”混为一谈很容易,因此请尽量使用正确的术语。 [...] 在 Redux 动作创建者中只需 return 一个动作

动作文档:动作是普通的JavaScript对象。

我的登录示例的伪代码:

function login() {
    // retrieving and serializing the state, then:
    localStorage.set('my_app_id_state', my_serialized_state);
    window.location = url_to_authorization_service;
}

此代码显然在动作创建器中没有位置,因为我没有 return 正在执行动作,而这正是动作创建器的目的。但是我仍然需要检索状态,所以我也不能让它完全独立。

所以问题又来了,我应该把这段代码放在我的应用程序结构中的什么地方?

同样,代码可以运行并且一切正常,所以我想这更像是一个学术问题,但它让我很烦恼,因为我在这里显然违反了 Redux 的基本规则。也许这只是一个例外?

这是一个很好的问题,让我意识到我做错了什么。所以希望这个答案至少对双方都有帮助:)

以改编自 Real World Redux example 的这个例子为例:

私有函数

function oauth(url) {
 return (dispatch) => {
   dispatch({
    type: types.OAUTH_LOGIN,
    url
   });
 };
}

由动作创建者调用(returns 一个函数)

export function loginToApi(redirectUrl) {
  return (dispatch) => {
    return dispatch(oauth(redirectUrl))
  }
}

然后在组件中依次调用动作,像这样:

login() {
 return this.props.dispatch(loginToApi());
}

因此,回答您问题的一种方法是将您的业务逻辑放入私有方法中,然后由操作创建者调用。

可能有更优雅的方法,但我在上面提到的文档中就是这样做的。

关于在本地存储中存储状态的登录逻辑:我认为您不需要这个。 Redux store 正在为您管理状态。

Dan Abramov 在 Twitter 上回复,我将得出结论,这是文档中概述的规则的例外情况。