【问题标题】:How do you remove query params from the current route?如何从当前路由中删除查询参数?
【发布时间】:2018-11-29 20:07:00
【问题描述】:

我有一个/cart 路由,它接受两个名为validateemail 的查询参数。它们仅在用户未登录时使用,并且在用户登录时是不必要的。在后一种情况下,我想将它们从 URL 中删除。

这是我当前用于/cart 路由的onEnter 函数:

const requireCartLogin = (props, replace) => {
    const { email, validate } = props.location.query;

    // Exit process if the 'validate' query isn’t present.
    if (typeof validate === 'undefined') { return; }

    if (!isAuthenticated() || requiresReauthentication()) {
        replace({
            pathname: '/account/signin',
            query: { step: 'signin' },
            state: {
                email: typeof email !== 'undefined' ? email : null,
                auth: true,
                next: '/cart'
            }
        });
    } else if (isAuthenticated()) {
        replace({
            pathname: '/cart',
            query: null
        });
    }
};

条件的第二部分应该删除查询参数,但它目前不起作用。我在这里错过了什么?

【问题讨论】:

  • 你有replace函数的代码吗?可以贴在这里吗?
  • @ChetanJadhavCD — 这只是 react-router 历史 API 的一部分:github.com/ReactTraining/react-router/blob/…
  • 您使用的是哪个版本的react-router
  • 我正在使用3.0.4

标签: reactjs react-router history.js


【解决方案1】:

看看 Dimitry Dushin 的 example

像这样创建 2 个实用函数:

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

请注意,这不适用于 >v4 of react-router

【讨论】:

    【解决方案2】:

    我搜索了一段时间如何做到这一点,最终意识到我需要做的就是像往常一样使用历史推送到 url(没有参数):

    // this piece of code is in /app/settings/account
    React.useEffect(() => {
    
            let params = queryString.parse(location.search)
            if (params && params.code) {
                doSomething(params.code)                                                            
                history.push('/app/settings/account')           
            }
        
    }, [])
    

    【讨论】:

      【解决方案3】:

      假设react-router-dom

      删除是最棘手的部分,因此首先您需要能够以合理的格式获取当前参数。

      您可以通过useLocation 挂钩以字符串形式获取搜索参数。

      但是处理这样的字符串会让人困惑,我更喜欢处理对象。

      例如?filter=123&amp;filter=something&amp;page=1 会产生以下对象。

      {
          filter: ['123', 'something'],
          page: ['1']
      }
      

      更容易操作。

      所以我们应该创建2个实用函数,一个将搜索字符串转换为上述对象,一个将对象转换回搜索字符串。

      toParamObject.js

      const toParamObject = (queryString) => {
        const params = new URLSearchParams(queryString);
        let paramObject = {};
        params.forEach((value, key) => {
          if (paramObject[key]) {
            paramObject = {
              ...paramObject,
              [key]: [
                ...paramObject[key],
                value,
              ],
            };
          } else {
            paramObject = {
              ...paramObject,
              [key]: [value],
            };
          }
        });
      
        return paramObject;
      };
      

      toQueryString.js

      const toQueryString = (paramObject) => {
        let queryString = '';
        Object.entries(paramObject).forEach(([paramKey, paramValue]) => {
          if (paramValue.length === 0) {
            return;
          }
          queryString += '?';
          paramValue.forEach((value, index) => {
            if (index > 0) {
              queryString += '&';
            }
            queryString += `${paramKey}=${value}`;
          });
        });
      
        // This is kind of hacky, but if we push '' as the route, we lose 
        // our page, and base path etc.
        // So instead.. pushing a '?' just removes all the current query strings
        return queryString !== '' ? queryString : '?';
      };
      

      得到

      // search is from useLocation, and we can just pass in the name of the param we want
      const get = (key) => toParamObject(search)[key] || [];
      

      删除

      const remove = (key, value) => {
          // First get the current params get()
          const thisParam = get(param).filter((val) => val !== value);
          const newParamObject = {
            ...toParamObject(search), // from useLocation
            [param]: thisParam,
          };
          push(`${toQueryString(newParamObject)}`); // from useHistory
      };
      

      【讨论】:

        【解决方案4】:

        您可以简单地覆盖history.push 中的搜索参数,如下所示:

        history.push({
            pathname: 'what/ever/your/path/is',
            search: '',
        });
        

        【讨论】:

          猜你喜欢
          • 2018-05-18
          • 2023-01-20
          • 1970-01-01
          • 2021-10-19
          • 2021-04-19
          • 2020-09-19
          • 2019-06-18
          • 1970-01-01
          • 2017-06-12
          相关资源
          最近更新 更多