Welcome to ShenZhenJia Knowledge Sharing Community for programmer and developer-Open, Learning and Share
menu search
person
Welcome To Ask or Share your Answers For Others

Categories

Users redirected to my app after login (server on java), and they have url, which looks like this http://10.8.0.29:8083/html/?locale=RU&token=1c5c71f2-dcda-4a51-8cf6-f8f6ff1031d0&returnTo=http://10.8.0.23:8080/

(with some params, html - is folder where sources located). I need to preserve this params while navigate on my app. So far I didn't found any simple solution to this problem except this How to redirect with react-router while preserving initial query parameters? old question, so I arise this question again, in hope. Thanks in advance.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
thumb_up_alt 0 like thumb_down_alt 0 dislike
358 views
Welcome To Ask or Share your Answers For Others

1 Answer

I already shared my solution for react-router v3 in the comment to your question.

Below is my solution for react-router v4.

Use the following createPreserveQueryHistory function to override history.push and history.replace methods so they will preserve specified query parameters:

import queryString from 'query-string';
import {createBrowserHistory} from 'history'

function preserveQueryParameters(history, preserve, location) {
    const currentQuery = queryString.parse(history.location.search);
    if (currentQuery) {
        const preservedQuery = {};
        for (let p of preserve) {
            const v = currentQuery[p];
            if (v) {
                preservedQuery[p] = v;
            }
        }
        if (location.search) {
            Object.assign(preservedQuery, queryString.parse(location.search));
        }
        location.search = queryString.stringify(preservedQuery);
    }
    return location;
}

function createLocationDescriptorObject(location, state) {
    return typeof location === 'string' ? { pathname: location, state } : location;
}

function createPreserveQueryHistory(createHistory, queryParameters) {
    return (options) => {
        const history = createHistory(options);
        const oldPush = history.push, oldReplace = history.replace;
        history.push = (path, state) => oldPush.apply(history, [preserveQueryParameters(history, queryParameters, createLocationDescriptorObject(path, state))]);
        history.replace = (path, state) => oldReplace.apply(history, [preserveQueryParameters(history, queryParameters, createLocationDescriptorObject(path, state))]);
        return history;
    };
}

const history = createPreserveQueryHistory(createBrowserHistory, ['locale', 'token', 'returnTo'])();

Then use it in your router definition:

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

For those who use TypeScript:

import {History, LocationDescriptor, LocationDescriptorObject} from 'history'
import queryString from 'query-string'
import LocationState = History.LocationState

type CreateHistory<O, H> = (options?: O) => History & H

function preserveQueryParameters(history: History, preserve: string[], location: LocationDescriptorObject): LocationDescriptorObject {
    const currentQuery = queryString.parse(history.location.search)
    if (currentQuery) {
        const preservedQuery: { [key: string]: unknown } = {}
        for (let p of preserve) {
            const v = currentQuery[p]
            if (v) {
                preservedQuery[p] = v
            }
        }
        if (location.search) {
            Object.assign(preservedQuery, queryString.parse(location.search))
        }
        location.search = queryString.stringify(preservedQuery)
    }
    return location
}

function createLocationDescriptorObject(location: LocationDescriptor, state?: LocationState): LocationDescriptorObject {
    return typeof location === 'string' ? {pathname: location, state} : location
}

export function createPreserveQueryHistory<O, H>(createHistory: CreateHistory<O, H>,
                                                 queryParameters: string[]): CreateHistory<O, H> {
    return (options?: O) => {
        const history = createHistory(options)
        const oldPush = history.push, oldReplace = history.replace
        history.push = (path: LocationDescriptor, state?: LocationState) =>
            oldPush.apply(history, [preserveQueryParameters(history, queryParameters, createLocationDescriptorObject(path, state))])
        history.replace = (path: LocationDescriptor, state?: LocationState) =>
            oldReplace.apply(history, [preserveQueryParameters(history, queryParameters, createLocationDescriptorObject(path, state))])
        return history
    }
}

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
thumb_up_alt 0 like thumb_down_alt 0 dislike
Welcome to ShenZhenJia Knowledge Sharing Community for programmer and developer-Open, Learning and Share
...