【问题标题】:How do you programmatically update query params in react-router?您如何以编程方式更新 react-router 中的查询参数?
【发布时间】:2017-03-02 20:55:39
【问题描述】:

如果不使用<Link/>,我似乎无法找到如何使用 react-router 更新查询参数。 hashHistory.push(url) 似乎没有注册查询参数,而且您似乎不能将查询对象或任何东西作为第二个参数传递。

如何在不使用<Link> 的情况下将react-router 中的url 从/shop/Clothes/dresses 更改为/shop/Clothes/dresses?color=blue

onChange 函数真的是监听查询变化的唯一方法吗?为什么不会像参数更改那样自动检测和响应查询更改?

【问题讨论】:

标签: reactjs react-router


【解决方案1】:

hashHistorypush 方法中,您可以指定查询参数。例如,

history.push({
  pathname: '/dresses',
  search: '?color=blue'
})

history.push('/dresses?color=blue')

您可以查看此repository,了解有关使用history 的更多示例

【讨论】:

  • 太棒了!无论如何要传递查询对象 {color: blue, size: 10} 而不是字符串?
  • @claireablani 目前,我认为不支持
  • @claireablani 你可以试试这个router.push({ pathname: '/path', state: { color: 'blue', size: 10 }, });
  • 只是为了澄清,这不再适用于反应路由器 v4。为此,请参阅@kristupas-repečka 的回答
  • 我们生活的时代不稳定。
【解决方案2】:

使用 react-router v4、redux-thunk 和 react-router-redux(5.0.0-alpha.6) 包的示例。

当用户使用搜索功能时,我希望他能够将相同查询的 url 链接发送给同事。

import { push } from 'react-router-redux';
import qs from 'query-string';

export const search = () => (dispatch) => {
    const query = { firstName: 'John', lastName: 'Doe' };

    //API call to retrieve records
    //...

    const searchString = qs.stringify(query);

    dispatch(push({
        search: searchString
    }))
}

【讨论】:

  • react-router-redux 已弃用
  • 我认为现在必须通过渲染<Redirect>标签来完成,链接到docs page
  • 您可以将您的组件包装在 withReducer HOC 中,这将为您提供 history 属性。然后你可以运行history.push({ search: querystring }
  • 您可以使用connected-react-router,而不是react-router-redux,它未被弃用。
【解决方案3】:

John's answer 是正确的。当我处理参数时,我还需要URLSearchParams 接口:

this.props.history.push({
    pathname: '/client',
    search: "?" + new URLSearchParams({clientId: clientId}).toString()
})

您可能还需要使用withRouter HOC 来包装您的组件,例如。 export default withRouter(YourComponent);.

【讨论】:

  • 这里不需要使用.toString(),因为添加问号会自动强制。
【解决方案4】:

您可以使用 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} />
}

这会保留历史记录,而不是在每次更改时都推送新路径

【讨论】:

    【解决方案5】:
        for react-router v4.3, 
    
     const addQuery = (key, value) => {
      let pathname = props.location.pathname; 
     // returns path: '/app/books'
      let searchParams = new URLSearchParams(props.location.search); 
     // returns the existing query string: '?type=fiction&author=fahid'
      searchParams.set(key, value);
      this.props.history.push({
               pathname: pathname,
               search: searchParams.toString()
         });
     };
    
      const removeQuery = (key) => {
      let pathname = props.location.pathname; 
     // returns path: '/app/books'
      let searchParams = new URLSearchParams(props.location.search); 
     // returns the existing query string: '?type=fiction&author=fahid'
      searchParams.delete(key);
      this.props.history.push({
               pathname: pathname,
               search: searchParams.toString()
         });
     };
    
    
     ```
    
     ```
     function SomeComponent({ location }) {
       return <div>
         <button onClick={ () => addQuery('book', 'react')}>search react books</button>
         <button onClick={ () => removeQuery('book')}>remove search</button>
       </div>;
     }
     ```
    
    
     //  To know more on URLSearchParams from 
    [Mozilla:][1]
    
     var paramsString = "q=URLUtils.searchParams&topic=api";
     var searchParams = new URLSearchParams(paramsString);
    
     //Iterate the search parameters.
     for (let p of searchParams) {
       console.log(p);
     }
    
     searchParams.has("topic") === true; // true
     searchParams.get("topic") === "api"; // true
     searchParams.getAll("topic"); // ["api"]
     searchParams.get("foo") === null; // true
     searchParams.append("topic", "webdev");
     searchParams.toString(); // "q=URLUtils.searchParams&topic=api&topic=webdev"
     searchParams.set("topic", "More webdev");
     searchParams.toString(); // "q=URLUtils.searchParams&topic=More+webdev"
     searchParams.delete("topic");
     searchParams.toString(); // "q=URLUtils.searchParams"
    
    
    [1]: https://developer.mozilla.org/en-US/docs/Web/API/URLSearchParams
    

    【讨论】:

      【解决方案6】:

      你可以使用钩子useHistory 确保您使用的是基于 function 的组件 在顶部导入这个

      import {useHistory} from "react-router-dom"
      

      在您的组件中,

      const history = useHistory()
      history.push({
          pathname: window.location.pathname,
          search: '?color=blue'
      })
      

      【讨论】:

        【解决方案7】:

        来自DimitriDushkin on 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);
        };
        

        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);
        

        【讨论】:

        • 这是 react-router v3 版本,后续版本不支持
        【解决方案8】:

        当您需要一个模块来轻松解析查询字符串时,推荐使用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("/"));
            }
        }
        

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

        我正在使用查询字符串模块解析它,保存它并使用来自react-router-redux 的推送更新 url 中的查询参数。

        【讨论】:

          【解决方案9】:

          也可以这样写

          this.props.history.push(`${window.location.pathname}&page=${pageNumber}`)
          

          【讨论】:

            【解决方案10】:

            我更喜欢你使用下面ES6风格的函数:

            getQueryStringParams = query => {
                return query
                    ? (/^[?#]/.test(query) ? query.slice(1) : query)
                        .split('&')
                        .reduce((params, param) => {
                                let [key, value] = param.split('=');
                                params[key] = value ? decodeURIComponent(value.replace(/\+/g, ' ')) : '';
                                return params;
                            }, {}
                        )
                    : {}
            };
            

            【讨论】:

              【解决方案11】:

              在我的情况下,输入输入字段将其作为查询字符串输出到浏览器的 url,使用如下所示的 React JS 功能组件

              
              import React, { useEffect, useState } from 'react'
              import { useHistory } from 'react-router-dom'
              
              const Search = () => {
                const [query, setQuery] = useState('')
                const history = useHistory()
              
                const onChange = (e) => {
                  setQuery(e.target.value)
                }
              
                useEffect(() => {
                  const params = new URLSearchParams()
                  if (query) {
                    params.append('name', query)
                  } else {
                    params.delete('name')
                  }
                  history.push({ search: params.toString() })
                }, [query, history])
              
                return <input type="text" value={query} onChange={onChange} />
              }
              
              export default Search
              
              
              

              浏览器的网址查询

              /search?name=query_here

              【讨论】:

                猜你喜欢
                • 2017-10-23
                • 2018-11-15
                • 1970-01-01
                • 2018-10-23
                • 1970-01-01
                • 2016-05-23
                • 2015-11-19
                • 2017-01-31
                • 2013-05-10
                相关资源
                最近更新 更多