Preserve query parameters in react-router

后端 未结 2 929
难免孤独
难免孤独 2020-12-20 14:02

In my react application I have a few parameters that the user comes to the application that provide some information about where they came from. Is there a way using react-r

相关标签:
2条回答
  • 2020-12-20 14:45

    In this case you can use a Store that holds URL state and you can use browserHistory to push custom history state.

    https://github.com/reactjs/react-router/blob/master/docs/guides/Histories.md#browserhistory

    import { browserHistory } from 'react-router'
    
    browserHistory.push({});
    

    Here is a link how to navigate outside components

    0 讨论(0)
  • 2020-12-20 14:51

    UPDATE

    Solution for react-router v4 is available.

    Solution for react-router v3:

    I wrote this little history v3 (it's compatible with react-router v3) enhancer in Typescript. It will preserve given set of query parameters. Be careful - history passed to this function has to be enhanced with useQueries.

    import {History, Location, LocationDescriptor} from 'history'
    
    export default function preserveQueryHistory(history: History, queryParameters: string[]): History {
        function preserveQueryParameters(path: LocationDescriptor): Location {
            const location = history.createLocation(path)
            const currentQuery = history.getCurrentLocation().query
            for (let p of queryParameters) {
                const v = (currentQuery as any)[p]
                if (v) {
                    location.query[p] = v
                }
            }
            return location
        }
        return {
            ...history,
            push(path: LocationDescriptor) {
                history.push(preserveQueryParameters(path))
            },
            replace(path: LocationDescriptor) {
                history.replace(preserveQueryParameters(path))
            }
        }
    }
    

    Now use it to create history:

    import useQueries from 'history/lib/useQueries'
    import createBrowserHistory from 'history/lib/createBrowserHistory'
    import preserveQueryHistory from './preserveQueryHistory'
    
    const history = preserveQueryHistory(useQueries(createBrowserHistory)(), ['language'])
    

    And in react-router:

    <Router history={history}>
    ...
    </Router>
    

    More ultimate solution with CreateHistory enhancer function that embeds applying useQueries enhancer and provides ability to inject custom History enhancer:

    import {CreateHistory, History, HistoryOptions, HistoryQueries, Location, LocationDescriptor} from 'history'
    import useQueries from 'history/lib/useQueries'
    
    function preserveQueryParameters(history: History, queryParameters: string[], path: LocationDescriptor): Location {
        const location = history.createLocation(path)
        const currentQuery = history.getCurrentLocation().query
        for (let p of queryParameters) {
            const v = (currentQuery as any)[p]
            if (v) {
                location.query[p] = v
            }
        }
        return location
    }
    
    function enhanceHistory<H>(history: History & H, queryParameters: string[]): History & H {
        return Object.assign({}, history, {
            push(path: LocationDescriptor) {
                history.push(preserveQueryParameters(history, queryParameters, path))
            },
            replace(path: LocationDescriptor) {
                history.replace(preserveQueryParameters(history, queryParameters, path))
            }
        })
    }
    
    export function createPreserveQueryHistoryWithEnhancer<O, H, H2>(createHistory: CreateHistory<O, H>,
        queryParameters: string[], enhancer: (h: History) => History & H2): CreateHistory<O, H & H2 & HistoryQueries> {
        return function (options?: HistoryOptions & O): History & H & H2 & HistoryQueries {
            let h = enhancer(useQueries(createHistory)(options)) as History & H & H2 & HistoryQueries
            return enhanceHistory<H & H2 & HistoryQueries>(h, queryParameters)
        }
    }
    
    export function createPreserveQueryHistory<O, H>(createHistory: CreateHistory<O, H>,
        queryParameters: string[]): CreateHistory<O, H & HistoryQueries> {
        return createPreserveQueryHistoryWithEnhancer<O, H, {}>(createHistory, queryParameters, h => h)
    }
    
    export function preserveQueryHistoryWithEnhancer<H, H2>(history: History & H, queryParameters: string[],
        enhancer: (h: History) => History & H2): History & HistoryQueries & H & H2 {
        return createPreserveQueryHistoryWithEnhancer(
            function () {
                return history
            },
            queryParameters, enhancer)()
    }
    
    export function preserveQueryHistory<H>(history: History & H, queryParameters: string[]): History & HistoryQueries & H {
        return preserveQueryHistoryWithEnhancer<H, {}>(history, queryParameters, h => h)
    }
    

    Usage with syncHistoryWithStore react-router-redux v4 History enhancer:

    import createBrowserHistory from 'history/lib/createBrowserHistory'
    import {createPreserveQueryHistoryWithEnhancer} from './preserveQueryHistory'
    import {syncHistoryWithStore} from 'react-router-redux'
    
    const store = ...
    
    const history = createPreserveQueryHistoryWithEnhancer(createBrowserHistory, ['language'], function (h: History) {
        return syncHistoryWithStore(h, store)
    })()
    
    0 讨论(0)
提交回复
热议问题