88

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

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

  1. Redux reducer 中的 searchState 应该使用新的搜索值更新(id=123 和 size=45)
  2. URL 应更改为“ 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 等)?

4

6 回答 6

79

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

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

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

于 2016-04-15T22:20:31.437 回答
17

简而言之:您可以使用redux-query-sync来保持存储中的 URL 参数和字段同步。它可以在没有任何路由器的情况下工作。


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

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

于 2017-06-27T18:37:23.907 回答
5

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

我想在这里分享几点:

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

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

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

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

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

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

于 2019-12-18T09:36:24.907 回答
2

我会推荐新工具react-url-query,它可以非常直接地进行同步。

于 2018-01-23T13:40:10.200 回答
2

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

  • 当输入值改变时,它的组件会触发一个回调,该回调是作为 prop 从其容器传递的。

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

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

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

关于相反的情况,我真的不确定。似乎手动设置 URL 会触发完全重新加载,但我可能弄错了。

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

于 2016-04-13T16:07:02.533 回答
2

我最近完成了与此类似的问题的工作。我使用 MobX 作为我的 store 和 redux-router 作为我的路由器。(我在 react-router 上做得很好,但是我需要在组件之外调度一个推送操作——redux 作为一个全局存储在这里工作得很好)

我的解决方案类似于 cantera 所描述的 - 我的路由器状态只是表单状态的反映。这还有一个额外的好处,那就是不必放弃我的表单状态并完全依赖于路由器状态。


在第一个场景中,

1)我像往常一样更新我的表单输入,这会触发结果组件中的重新渲染。

2)在componentDidUpdate()结果组件中,我使用表单道具来构造更新的查询字符串。

3)我将更新的查询字符串推送到路由器状态。这纯粹是为了更新 URL 的效果。


对于第二种情况

1)在onEnterRoute组件的钩子中,我获取了可用的查询字符串并将其解析为初始表单值。

2)我用这些值更新我的商店。这仅适用于页面的第一次加载,也是路由器状态指示表单状态的唯一时间。


编辑:当您返回浏览器历史记录时,此解决方案不考虑这种情况,因为 url 不会更新您的状态。

于 2016-08-12T10:44:00.743 回答