【问题标题】:Is there a way to store part of application state in URL query with React+Redux?有没有办法使用 React+Redux 在 URL 查询中存储部分应用程序状态?
【发布时间】:2017-06-14 21:54:01
【问题描述】:

我正在使用 React、Redux 和 React Router。我想将大部分应用程序状态存储在 redux 存储中,并将其中的一些位存储在 URL 查询中。我相信有两种方法可以做到这一点:

  • 在每次状态更改后将 redux 存储与 URL 查询同步
  • 不要在 redux 存储中存储“一些位”,而是通过某种方式(类似于 reducer 的工作方式)来更改 URL 查询,就好像它是另一个存储一样

我不确定第一种方法是否可行,因为序列化状态长度可能超过 URL 限制。所以我可能应该选择第二个。

例如,我在一个页面上有几个复选框,我希望它们的状态(选中/未选中)反映在 URL 中,因此我可以将我的 URL 链接发送给其他人,他们会像我一样选中相同的复选框.所以我像这样渲染我的复选框:

export class MyComponent extends React.Component {

    handleCheckboxClick(...) {
        // Some magic function, that puts my urlState into URL query.
        updateUrlState(...)
    }

    render() {
        // 'location' prop is injected by react router.
        const urlState = getUrlState(this.props.location.query);  

        // Let's say 'checkboxes' are stored like so:
        // {
        //     foo: false,
        //     bar: true,
        // }
        const { checkboxes } = urlState;

        return (
            <div>
                { checkboxes.map(
                    (checkboxName) => <Checkbox checked={ checkboxes[checkboxName] } onClick={ this.handleCheckboxClick }>{ checkboxName }</Checkbox>
                )}
            </div>
        )
    }

}

我想要魔术updateUrlState 函数做的是获取当前 URL 查询,更新它(将某些复选框标记为选中)并将结果推送回 URL 查询。

由于这个临时的 URL 状态可能是嵌套的和复杂的,它可能应该被序列化并存储为 JSON,因此生成的 URL 看起来有点像:https://example.com/#/page?checkboxes="{"foo":false,"bar":true}"。

这可能吗?

【问题讨论】:

标签: javascript reactjs ecmascript-6 redux


【解决方案1】:

参考这个 Modify the URL without reloading the page

当复选框被选中/取消选中时,您可以简单地调度一个动作,这将调用您的魔术 url 函数以使用 window.history.pushState() 更改 url

function changeUrl() {
  isChecked = state.get('checkBox');
  window.history.pushState(state, '', 'isChecked=' + isChecked)
}

上面的第一个参数是当用户点击返回按钮时,浏览器会发出popstate事件,你可以使用状态来设置你的ui。见https://developer.mozilla.org/en-US/docs/Web/API/History_API

然后当其他用户粘贴 url 时,您可能只想解析 url 并在 componentDidMount 中的商店中设置正确的状态。

function decodeUrl() {
  let params = window.location.href.replace(baseUrl, '');
  // parse your params and set state
}

仅供参考:网址不支持某些字符(例如“{”)。因此,您需要将它们解析为查询参数,或对其进行编码。试试这个工具http://www.urlencoder.org/

【讨论】:

  • 在不重新加载的情况下修改 URL 没有问题,我只是不想每次用户单击复选框时都手动进行。我正在寻找类似 redux reducers 的东西,但用于 URL 查询。
  • @roboslone 不确定你所说的 redux reducer 是什么意思。您可以在状态更改时调度操作并修改 url?
  • @roboslone github.com/reactjs/react-router-redux 可以帮助你。见syncHistoryWithStore
【解决方案2】:

如果我解决了您的问题,那么redux middleware 可以在这里为您提供真正的帮助。中间件有点像 reducer,但位于从 action 到 reducer 的流程之间。这种用例的最佳示例是日志记录,我开发了处理所有远程请求的中间件。基本上你在中间件中得到了调度的动作,你可以在那里分析它。如果某个操作应该更改应用程序的查询参数,您可以从那里分派新的操作。

所以您的代码可能如下所示:

const queryChanges = store => next => action => {
  if (/*here you test the action*/) {
    //here can change the url, or
    return dispatch(actionToTriggerURLChange());

  } else {
    return next(action);
  }
}

如果您既不打电话给return next(action),也不派遣新的,什么都不会发生,所以请记住这一点。

查看文档并了解中间件的所有工作原理,我猜这种方法在这种情况下将是最“不重复”的。

【讨论】:

  • 我最终编写了自己的方法来将应用程序状态的一部分存储在 URL 中,而不是中间件。
猜你喜欢
  • 1970-01-01
  • 2022-01-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-09-26
  • 2018-11-14
  • 1970-01-01
相关资源
最近更新 更多