56

I know we can replace query params in component based classes doing something along the lines of:

  componentDidMount() {       
    const { location, replace } = this.props;   

    const queryParams = new URLSearchParams(location.search);   
    if (queryParams.has('error')) { 
      this.setError(    
        'There was a problem.'  
      );    
      queryParams.delete('error');  
      replace({ 
        search: queryParams.toString(), 
      });   
    }   
  }

Is there a way to do it with react hooks in a functional component?

2 Answers 2

83

For React Router V6 and above, see the answer below.


Original Answer:

Yes, you can use useHistory & useLocation hooks from react-router:


import React, { useState, useEffect } from 'react'
import { useHistory, useLocation } from 'react-router-dom'

export default function Foo() {
  const [error, setError] = useState('')

  const location = useLocation()
  const history = useHistory()

  useEffect(() => {
    const queryParams = new URLSearchParams(location.search)
    
    if (queryParams.has('error')) {
      setError('There was a problem.')
      queryParams.delete('error')
      history.replace({
        search: queryParams.toString(),
      })
    }
  }, [])

  return (
    <>Component</>
  )
}

As useHistory() returns history object which has replace function which can be used to replace the current entry on the history stack.

And useLocation() returns location object which has search property containing the URL query string e.g. ?error=occurred&foo=bar" which can be converted into object using URLSearchParams API (which is not supported in IE).

Sign up to request clarification or add additional context in comments.

5 Comments

This won't work with Class Component, how to we handle it there.
In a class component, replace useEffect with componentDidMount, useState with this.state, useHistory with this.props.history + withRouter HOC. That should work with class component.
In case anyone is interested, to be used with function components I've created a library useClearParams github.com/oyalhi/use-clear-params#readme
useNavigate in react-router-dom v6
I've used this approach to update a search param based on user selection on the page, but this causes page reload, which is completely unnecessary in my case ...
46

Use useSearchParams hook.

import {useSearchParams} from 'react-router-dom';

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

  const removeErrorParam = () => {
    if (searchParams.has('error')) {
      searchParams.delete('error');
      setSearchParams(searchParams);
    }
  }

  return <button onClick={removeErrorParam}>Remove error param</button>
}

5 Comments

Note that this doesn't remove it from the url (which might be a little confusing depending on the use case) - useHistory is no more in v6 - so some variation of useNavigation would probably be needed... know how to navigate without triggering a re-render? If I recall last time I needed prevention of navigation I messed with navigator from UNSAFE_NavigationContext
stackoverflow.com/a/70700037/2848941 hmm .... seems extra navigation shouldn't be necessary, as long as it's in a useEffect?
Added this to my useEffect hook and it works like a charm.
is this still in react router v6?
This removes the query param from the URL in my app (react-router v6.10) without using useNavigate or useEffect

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.