Reactjs React Router-在不刷新页面的情况下更新浏览器历史记录

Reactjs React Router-在不刷新页面的情况下更新浏览器历史记录,reactjs,react-router,Reactjs,React Router,我遇到了react路由器的独特问题-我之所以说独特是因为我在文档中找不到任何东西 效果很好: /* ./LocationStore */ if (isRandom) { _isLoadingRandomLocation = true; const path = `/locations/${_data.id}`; browserHistory.replace(path) } /* ./Dashboard */ componentWillReceiveProps

我遇到了react路由器的独特问题-我之所以说独特是因为我在文档中找不到任何东西

效果很好:

/* ./LocationStore */
if (isRandom) {
    _isLoadingRandomLocation = true;
    const path = `/locations/${_data.id}`;
    browserHistory.replace(path)      
}

/* ./Dashboard */
componentWillReceiveProps(nextProps){
    // When the URL params change get locations
    if (nextProps.params !== this.props.params) {
        if (LocationStore.getIsLoadingRandomLocation()) {
            LocationStore.setIsLoadingRandomLocation(false);
        }
        else {
            LocationStore.getLocation(nextProps.params);
        }
    }
},

当用户在
/
路径加载以下react应用程序时,它们将被重定向到
/locations/random
路径,然后在
shouldComponentUpdate
块中触发API
GET
请求。一旦数据被检索并存储在
LocationStore
组件中,就会向
仪表板
组件发出一个事件,以使用检索到的数据呈现新行。一切都很好

问题区域:

/* ./LocationStore */
if (isRandom) {
    _isLoadingRandomLocation = true;
    const path = `/locations/${_data.id}`;
    browserHistory.replace(path)      
}

/* ./Dashboard */
componentWillReceiveProps(nextProps){
    // When the URL params change get locations
    if (nextProps.params !== this.props.params) {
        if (LocationStore.getIsLoadingRandomLocation()) {
            LocationStore.setIsLoadingRandomLocation(false);
        }
        else {
            LocationStore.getLocation(nextProps.params);
        }
    }
},
在数据被检索并存储到
LocationStore
之后,我想获取数据
data.id
id
属性,并将该值放入当前可见的url,即
locations/100
和not
locations/random
,以便用户可以在将来导航回来,但是当我做
browserHistory.push('locations/100')
它再次点击
路由器
,整个过程再次开始,这意味着再次检索相同的数据。有没有一种方法可以在不触发路由器的情况下更新可见URL并将其保存在
browserHistory
中?或者有没有办法创建一条新的
路线
,比如

import React from 'react'
import { render } from 'react-dom'
import { Router, Route, browserHistory, IndexRedirect} from 'react-router'
import {isInteger} from 'lodash'

let _data = {};
let _changeListeners = [];

render((
    <Router history={browserHistory}>
        <Route path="/" component={App}>
            <IndexRedirect to="/locations/random"/>
            <Route path="/locations/:locationId" component={Dashboard}/>
        </Route>
    </Router>
), document.getElementById('app'));

const App = React.createClass({
    render() {
        return <div>Home</div>
    }
});

const Dashboard = React.createClass({

    getInitialState: function () {
        return {
            data: {}
        }
    },

    updateData(){
        // Once the LocationStore has sent out a notification that the data has changed, trigger a render of the dashboard
        this.setState({
            data: LocationStore.getData()
        });
    },

    shouldComponentUpdate (nextProps) {
        // Trigger a request to load new data when the url changes
        LocationStore.getLocation(nextProps.params);
        return true;
    },

    componentDidMount() {
        LocationStore.addChangeListener(this.updateData);
    },

    componentWillUnmount() {
        LocationStore.removeChangeListener(this.updateData);
    },

    render() {
        return (
            <div>
                <div className="page-container" style={{ paddingBottom: 20}}>
                    <div className="col-lg-12">
                        <h2>Display Data Here as a Row</h2>
                    </div>
                </div>
            </div>
        )
    }
});

const LocationStore = {

    getLocation: function (params) {
        // Get location by id or random
        const isRandom = !isInteger(params.locationId);
        var url = (isRandom) ? "/api/locations/random" : `/api/locations/${params.locationId}`;
        Utils.getJSON(url, function (err, res) {
            _data = res;

            // If the user hit the random route, update the URL here to show the id of the record brought down
            if (isRandom) {
                const path = `/locations/${_data.id}`;
                browserHistory.push(path);
            }

            LocationStore.notifyChange();
        })
    },

    getData: function () {
        return _data;
    },

    notifyChange: function () {
        _changeListeners.forEach(function (listener) {
            listener()
        })
    },

    addChangeListener: function (listener) {
        _changeListeners.push(listener)
    },

    removeChangeListener: function (listener) {
        _changeListeners = _changeListeners.filter(function (l) {
            return listener !== l
        })
    }
};

const Utils = {
    getJSON: function (url, cb) {
        const req = new XMLHttpRequest();
        req.onload = function () {
            if (req.status === 404) {
                cb(new Error('not found'))
            } else {
                cb(null, JSON.parse(req.response))
            }
        };
        req.open('GET', url);
        req.send()
    }
};

听起来您想在这里使用
replaceState
,而不是
pushState
replaceState
将使用提供的URL替换历史记录条目,因此,用户似乎从未访问过您的/随机URL

相关API:


参考:

谢谢@michael camden。这很有效,正是我所需要的。现在,我需要找到一种方法,在
this.props.params
发生更改时触发新的数据更新,因为
shouldComponentUpdate
似乎触发频率太高。
shouldComponentUpdate
应该用作防止更新的手段,而不是对更新采取行动<代码>组件更新是正确的生命周期事件。