我似乎找不到如何更新查询参数与反应路由器不使用<Link/>。hashHistory.push(url)似乎没有注册查询参数,而且似乎不能将查询对象或任何东西作为第二个参数传递。

如何将url从/shop/Clothes/dresses更改为/shop/Clothes/dresses?color=blue在反应路由器没有使用<链接>?

onChange函数真的是侦听查询更改的唯一方法吗?为什么不自动检测和响应查询更改-以参数更改的方式?


当前回答

DimitriDushkin在GitHub上写道:

import { browserHistory } from 'react-router';

/**
 * @param {Object} query
 */
export const addQuery = (query) => {
  const location = Object.assign({}, browserHistory.getCurrentLocation());

  Object.assign(location.query, query);
  // or simple replace location.query if you want to completely change params

  browserHistory.push(location);
};

/**
 * @param {...String} queryNames
 */
export const removeQuery = (...queryNames) => {
  const location = Object.assign({}, browserHistory.getCurrentLocation());
  queryNames.forEach(q => delete location.query[q]);
  browserHistory.push(location);
};

or

import { withRouter } from 'react-router';
import { addQuery, removeQuery } from '../../utils/utils-router';

function SomeComponent({ location }) {
  return <div style={{ backgroundColor: location.query.paintRed ? '#f00' : '#fff' }}>
    <button onClick={ () => addQuery({ paintRed: 1 })}>Paint red</button>
    <button onClick={ () => removeQuery('paintRed')}>Paint white</button>
  </div>;
}

export default withRouter(SomeComponent);

其他回答

也可以这样写

this.props.history.push(`${window.location.pathname}&page=${pageNumber}`)
// react-router-dom v6

// import
import { useNavigate, createSearchParams } from 'react-router-dom';

// useSearchParams hook
const [searchParams, setSearchParams] = useSearchParams();

// usage
const params: URLSearchParams = new URLSearchParams();
params.id = '123';
params.color = 'white';

// set new parameters
setSearchParams(params);

! !当心!!这将只更新当前页面上的查询参数,但您将无法导航回(浏览器返回btn)到以前的路由,因为此选项不会更改历史记录。要使此行为到位,请检查之前的答案:https://stackoverflow.com/users/6160270/rakesh-sharma的答案

您可以使用replace功能,而不是在每次更改时推送一个新路由

import React from 'react';
import { useHistory, useLocation } from 'react-router';

const MyComponent = ()=>{
   const history = useHistory();
   const location = useLocation();

   const onChange=(event)=>{
     const {name, value} = event?.target;
     const params = new URLSearchParams({[name]: value });
     history.replace({ pathname: location.pathname, search: params.toString() });       
   }

   return <input name="search" onChange={onChange} />
}

这保留了历史,而不是在每一个变化上都推一条新的道路

更新- 2022年2月(V6)

正如Matrix Spielt指出的那样,useHistory被usenavate取代来进行更改。还有一个方便的方法叫做useSearchParams,我只需要阅读文档,没有运行这个,但这应该可以工作

import React from 'react';
import { useSearchParams } from 'react-router-dom';
// import from react-router should also work but following docs
// import { useSearchParams } from 'react-router';

const MyComponent = ()=>{
   const [searchParams, setSearchParams] = useSearchParams();

   const onChange=(event)=>{
     const {name, value} = event?.target;
     setSearchParams({[name]: value})       
   }

   return <input name="search" onChange={onChange} />
}

我做了一个简单的钩子来减轻工作。

让我们想象一下你的url是这样的: /搜索吗?起源=主页= 1

function useUrl(param: string) {

    const history = useHistory()
    const { search, pathname } = useLocation()
    const url = new URLSearchParams(search)

    const urlParam = url.get(param)
    const [value, setValue] = useState(urlParam !== null ? urlParam : '')

    function _setValue(val: string){
        url.set(param, val)
        history.replace({ pathname, search: url.toString() }); 
        setValue(val)
    }

    return [value, _setValue]
}

那么实际使用情况:

function SearchPage() {

    const [origin] = useUrl("origin")
    const [page, setPage] = useUrl("page")

    return (
        <div>
            <p>Return to: {origin}</p>
            <p>Current Page: {page}</p>
        </div>
    )
}

当你需要一个模块来轻松地解析你的查询字符串时,推荐使用query-string模块。

http://localhost:3000?token=xxx-xxx-xxx

componentWillMount() {
    var query = queryString.parse(this.props.location.search);
    if (query.token) {
        window.localStorage.setItem("jwt", query.token);
        store.dispatch(push("/"));
    }
}

在这里,我从Node.js服务器重定向回我的客户端后,成功的Google-Passport身份验证,这是重定向回令牌作为查询参数。

我用query-string模块解析它,保存它并更新url中的查询参数,从react-router-redux推送。