如何同步 Redux 状态和 url 哈希标签参数

Posted

技术标签:

【中文标题】如何同步 Redux 状态和 url 哈希标签参数【英文标题】:How to sync Redux state and url hash tag params 【发布时间】:2016-08-11 21:06:26 【问题描述】:

我们有一个讲座和章节列表,用户可以在其中选择和取消选择它们。这两个列表存储在一个 redux 存储中。 现在我们希望在 url 的 hash 标记中保留所选讲座 slug 和章节 slug 的表示,并且对 url 的任何更改也应该更改存储(双向同步)。

使用react-router 甚至react-router-redux 的最佳解决方案是什么?

我们真的找不到一些好的例子,其中 react 路由器仅用于维护 url 的哈希标记,并且也只更新一个组件。

【问题讨论】:

为什么要将这个状态保存在 store 中,而不是仅仅使用 React Router 作为 URL 参数的真实来源,并使用它在 mapStateToProps(state, ownProps) 中注入的 props ? 因为url参数只包含了讲座的slug和被选中的章节。在商店中,我有一个讲座和章节列表,其中包含名称、slug 和选定的布尔值。 例如使用peterbeshai.com/react-url-query ? 【参考方案1】:

我认为你不需要。 (很抱歉给出了不屑一顾的答案,但这是我经验中最好的解决方案。)

存储是数据的真实来源。这很好。 如果你使用 React Router,让它成为你 URL 状态的真实来源。 您不必将所有东西都保留在商店中。

例如,考虑您的用例:

因为 url 参数只包含讲座的 slug 和选择的章节。在商店中,我有一个讲座和章节列表,其中包含名称、slug 和选定的布尔值。

问题是您正在复制数据。存储中的数据 (chapter.selected) 在 React Router 状态下被复制。一种解决方案是同步它们,但这很快就会变得复杂。为什么不让 React Router 成为选定章节的真实来源?

您的商店状态将如下所示(简化):


  // Might be paginated, kept inside a "book", etc:
  visibleChapterSlugs: ['intro', 'wow', 'ending'],

  // A simple ID dictionary:
  chaptersBySlug: 
    'intro': 
      slug: 'intro',
      title: 'Introduction'
    ,
    'wow': 
      slug: 'wow',
      title: 'All the things'
    ,
    'ending': 
      slug: 'ending',
      title: 'The End!'
    
  

就是这样!不要在那里存储selected。而是让 React Router 处理它。在您的路由处理程序中,编写类似

的内容
function ChapterList( chapters ) 
  return (
    <div>
      chapters.map(chapter => <Chapter chapter=chapter key=chapter.slug />)
    </div>
  )


const mapStateToProps = (state, ownProps) => 
  // Use props injected by React Router:
  const selectedSlugs = ownProps.params.selectedSlugs.split(';')

  // Use both state and this information to generate final props:
  const chapters = state.visibleChapterSlugs.map(slug => 
    return Object.assign(
      isSelected: selectedSlugs.indexOf(slug) > -1,
    , state.chaptersBySlug[slug])
  )

  return  chapters 


export default connect(mapStateToProps)(ChapterList)

【讨论】:

很抱歉这么晚才回来,但我上周正在度假。我有一个问题。您描述了一种从 url 获取数据并呈现它的方法。您将如何使用新选择的章节更新网址? 我会在动作创建器中调用browserHistory.push()(其中browserHistory 是从react-router 导入的)。我可能会使用 Redux Thunk 来明确它的副作用。我会在里面打电话给dispatch( ... ); browserHistory.push(...) 嘿,丹。感谢 Redux!我的我也把我的 2 美分放在这个话题上并提出一个问题。如果应用程序状态转换逻辑依赖于查询中的数据怎么办?这意味着减速器需要它,你不能只是在商店里摆脱它。 @AlexanderReshytko 由于这些数据来自“外部世界”,我会在必要时发出操作。这并不意味着您需要一个通用的“路由更改”操作(即使您发现它有用时可以调度它)。然后你的 reducer 就可以像往常一样使用这些信息了。 发送参数重新选择选择器有点别扭,所以能够从商店中获取当前的url参数非常有用。【参考方案2】:

react-router-redux可以帮你注入url的东西来存储,所以每次hash标签改变时,也要存储。

【讨论】:

它只是给你位置,而不是解析的参数,所以它的用处有限,除非你可以手动重新实现 React Router 给你的东西。这是一个很好的解决方案,可以使存储与操作保持同步以便记录和重放用户会话,但对于不需要它的应用来说,它并不是那么有用。

以上是关于如何同步 Redux 状态和 url 哈希标签参数的主要内容,如果未能解决你的问题,请参考以下文章

有没有办法先在选项卡之间同步 redux 存储状态,然后让每个选项卡控制自己的状态?

如何在不同的 URL 路由之间保存 redux 状态?

node.js 中的多人游戏架构 - 与 Redux 的状态管理和同步

如何在不同的URL路由之间保存redux状态?

如何从 ui-router 中的 url 地址中删除哈希标签 (#)

触发 Redux 操作以响应 React Router 中的路由转换