如何在React Router v4中操作历史记录?

时间:2017-07-04 23:22:36

标签: reactjs redux react-router react-redux react-router-redux

我正在使用:

React,Redux,React-Router,Meteor

以下情况:

我有一个带有两个标签的模态,根据所选标签,内容区域中会显示不同的选项列表,然后选择一个选择列表(所有模式内都有)。

所需行为

我希望用户能够使用浏览器的后退按钮“撤消”点击其中一个标签或选择一个选项。

到目前为止我尝试过但没有成功:

  1. 使用withRouter HOC来包装我的组件,这样我就可以访问历史记录了。然后我会使用history.push(currentUrl,{selectedTab:selection}) - >问题:来自push的状态未存储在此历史记录位置对象上,而是仅存储在与我的rootcomponent关联的历史记录对象的状态中(在树的上方)

  2. (目前为止更有前景)只需将我在createHistory中创建的历史记录导入另一个模块,并将其放入构造中的组件状态。 然后,我将使用this.state.history.push(currentUrl,{selectedTab:selection})访问push方法,该方法工作正常,我可以在this.state.history.location.state.selectedTab下找到推送状态。但是,使用浏览器的后退按钮不会导致重新渲染,因此选择将保持不变。

  3. 有什么想法吗?

    干杯

3 个答案:

答案 0 :(得分:0)

我改进了第二种方法,现在正在运作。将历史记录导入我的模块(作为局部变量)仍然感觉很麻烦,因此绕过反应树,redux存储并完全响应路由器。 但是,它正在工作,到目前为止没有造成任何错误。所以我们走了......

我将历史对象实例化为:
store.js模块

import createHistory from 'history/createBrowserHistory';
...
const history = createHistory();
...
export { history , store }

您可以看到导出历史记录。然后我将所述历史记录提供给我的路由器(在我的情况下为ConnectedRouter,因为我使用的是react-router-redux): routes.js module

import { store , history } from '/imports/client/store';

const MyStoreRouter = () => {
    return (
        <Provider store={store}>
            <ConnectedRouter history={ history }>
                <div>
                    <Switch>
                        <Route exact path="/" component={Landing}/>
                        <Route path="/" component={MainApp}/>
                    </Switch>
                </div>
            </ConnectedRouter>
        </Provider>
    );
};

现在是古怪的部分。我将历史记录导入显示组件并使用它来设置监听器(以表示history.location中的更改)并相应地更改状态:
DisplayComponent.js模块:

import { history } from '/imports/client/store';
....
export default class EventCreationModal extends Component {
    constructor() {
        super();
        this.handleSelect = this.handleSelect.bind(this);
        this.state = {
            selectedCategory: (history.location.state && history.location.state.category) ? history.location.state.category : 'sports',
        };
        history.listen((location,action) => {
            this.setState({
                selectedCategory: (history.location.state && history.location.state.category) ? history.location.state.category : 'sports',
            })
        }); 
    }

    handleSelect(key) {
        history.push("/Home",{'category':key})
    }

render () {
    return (
        <Tabs activeKey={this.state.selectedCategory} onSelect={this.handleSelect} id="SportOrSocialSelector">
            <Tab eventKey={'sports} .../>
            <Tab eventKey={'social} .../>
        </Tabs>
    )
}

答案 1 :(得分:0)

您可以采用的另一种方法是使用React路由器查询参数。在您的组件中,根据查询参数更改选项卡。由于网址已更改,因此您应该获得所需的默认行为。

答案 2 :(得分:0)

我的项目几乎就是这种情况。不同之处在于,不是它在模态中,而是在我的标题中。这是我做的:

import React, { Component } from 'react';
import { Link, withRouter } from 'react-router-dom';

class Header extends Component {
  render() {
    return (
      <ul className="tabs tabs-fixed-width z-depth-1">
        <li className="tab">
          <Link id="books-tab" to={'/books'}>Books</Link>
        </li>
        <li className="tab">
          <Link id="stats-tab" to={'/stats'}>Stats</Link>
        </li>
        {Meteor.userId() &&
          <li className="tab">
            <Link id="user-tab" to={'/user'}>Account Settings</Link>
          </li>}
      </ul>
    );
  }
}

export default withRouter(Header);

react-router-dom <Link>...是允许这种情况发生的操作项目。

然后,当我单击选项卡时,每个链接都会转到指定的URL并将其保留在历史记录中,以便我可以返回到上一个选项卡。