如何同步Redux状态和url查询参数

Ant*_*ton 64 react-router redux-framework redux react-redux react-router-redux

我有一个带搜索面板的网页.搜索面板有几个输入字段:id,size,...

我想要的是当用户设置搜索值(例如:id = 123和size = 45)并按下搜索按钮时:

  1. 应使用新搜索值(id = 123和size = 45)更新Redux reducer中的searchState
  2. 网址应更改为" http:// mydomain/home?id = 123&size = 45 "

另一方面,如果用户将URL更改为http:// mydomain/home?id = 111&size = 22,则:

  1. reducer中的searchState应该用新的搜索值更改(id = 111和size = 22)
  2. UI搜索面板输入应使用新值更新(id = 111和size = 22)

如何达成目标?我应该使用什么路由器(react-router,redux-router,react-router-redux ot other)?

Dan*_*mov 53

我建议直接使用React Router不是保留searchState在Redux中.React Router会将URL参数注入您的组件,您可以使用它们mapStateToProps(state, ownProps)来计算最终的道具.

如果您真的希望将路由更改视为操作,则可以使用react-router-redux进行双向同步,但它不会为您提供状态中的参数 - 只是当前位置.如果您想要记录和重放操作,并在重播时更新URL栏,则唯一的用例.

这绝不是必需的 - 在大多数情况下,直接使用React Router就足够了.


Ger*_*ben 12

简而言之:您可以使用redux-query-sync来保持商店中的URL参数和字段同步.它没有任何路由器.


更长的故事:挣扎着同样的问题,我首先赞赏Dan Abramov的回答,建议(在我看来)将URL视为"第二个商店",这是Redux商店之外的应用程序状态的一部分.但后来我发现有两种"存储"使得很难修改代码,例如将事物从一个移动到另一个,因为每个"存储"都有不同的接口.作为开发人员,我宁愿选择Redux状态中的任何字段,并在URL中公开它们,就好像该位置是我的状态(的一部分)的一个小窗口.

因此,我刚刚发布了redux-query-sync,让您提供一个选择器函数,用于从状态中选择一个值,然后在窗口位置以您指定的参数名称显示该值.为了让它在另一个方向同步,从URL到Redux状态(例如,当应用程序最初加载时),您可以提供将传递参数值的动作创建者,因此您的reducer可以相应地更新状态.


小智 5

我最近还为我公司的应用程序完成了此功能的开发。我们想向 URL 添加不同的搜索查询。

我想在这里分享一些事情:

1) 我们使用了 Redux store 和 react-router。由于我们也使用了 Typescript,我们最终使用了 react-router 中的 RouteComponentProps 来使用 this.props.history.push() 来更新 URL。

2) 我们将所有搜索查询都保存在 Redux 存储中。更新 Redux store 和 URL 的工作流程如下:

在应用程序中选择一些过滤选项 => 调度操作以更新 Redux 商店中的过滤状态 => 更新 URL

3) 最后,我们还希望用户能够输入带有查询参数的 URL,它会更新应用程序中的所有过滤器。为此,工作流程更加简单:

用户输入 URL => dispatch actions 以使用来自 URL 的查询参数更新 Redux 状态。Redux 状态的更新将自动导致应用程序中的重新渲染,并且所有过滤器都将更新。

所以这里最重要的是始终保持 Redux 状态和 URL 彼此同步。


can*_*era 3

这是我处理第一个场景的方式:

  • 当输入值更改时,其组件会触发从其容器作为 prop 传递的回调。

  • 在回调中,容器在事件发生时调度负责更新 Redux 状态的操作。

  • 在紧随操作调用之后的行中,我使用this.context.router.push()并向其传递带有正确查询字符串的 url。

我不确定这是正确的方法。我发现最好先更新 URL,因为在我看来,查询字符串应该是状态的反映,而不是状态的主宰。

至于相反的情况,我真的不确定。看起来手动设置 URL 会触发完全重新加载,但我可能是错的。

至于使用哪个路由器,我自己使用React Router。我并没有真正发现使用其他人的价值,而这次讨论对我来说是关键。