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


76

我们提供了讲座和章节的列表,用户可以在其中选择和取消选择它们。这两个列表存储在redux存储中。现在,我们希望在url的hash标签中保留选定的演讲段和章节段的表示形式,并且对该URL所做的任何更改也应更改存储(双向同步)。

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

我们真的找不到一些很好的示例,其中react路由器仅用于维护url的hash标签,并且仅更新一个组件。


4
您为什么要在商店中保留此状态,而不是仅将React Router用作URL参数的真实来源,并使用它注入到mapStateToProps(state,ownProps)中的道具?
Dan Abramov

2
因为url参数仅包含讲座和所选章节的内容。在商店中,我有一个讲座和章节列表,其中包含名称,子句和选定的布尔值。
JoKer '16

Answers:


149

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

存储是数据真实性的来源。这可以。
如果您使用React Router,则让它成为URL状态的真实来源。
您不必将所有物品都保留在商店中。

例如,考虑您的用例:

因为url参数仅包含讲座和所选章节的内容。在商店中,我有一个讲座和章节列表,其中包含名称,子句和选定的布尔值。

问题是您正在复制数据。存储区(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)

4
很抱歉回来这么晚,但上周我在放假。我有一个问题。您描述了一种从URL中获取数据并进行渲染的方法。您将如何使用新选择的章节更新网址?
约克(JoKer)'16

9
我会在动作创建者中调用browserHistory.push()browserHistory从中导入react-router)。我可能会使用Redux Thunk来表明存在副作用。我会打电话给dispatch({ ... }); browserHistory.push(...)里面。
丹·阿布拉莫夫

2
嘿,丹。感谢Redux!我也把2分钱放在这个话题上,并提出一个问题。如果应用程序状态转换逻辑依赖于查询中的数据怎么办?这意味着减速器需要它,而您不能只是在商店中摆脱它。
亚历山大·瑞希科

2
@AlexanderReshytko由于此数据来自“外部世界”,因此如有必要,我将对其采取行动。但这并不意味着您需要一个通用的“路由更改”操作(即使您发现有用的话也可以分派它)。然后,减速器可以像通常一样使用该信息。
丹·阿布拉莫夫

8
发送参数以重新选择选择器有点尴尬,因此能够从存储中获取当前的url参数非常有用。
雅各布·拉斯克

3

react-router-redux 可以帮助您注入要存储的url内容,因此每次哈希标签更改时,也要存储。


23
它只是为您提供位置,而不是解析后的参数,因此它的作用有限,除非您可以手动重新实现React Router给您的内容。这是使存储与动作保持同步以便记录和重播用户会话的一种很好的解决方案,但是对于不需要此功能的应用程序来说,它并不是那么有用。
Dan Abramov
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.