Home > Back-end >  Javascript does not recognise two url parameters as equal even though they are equal
Javascript does not recognise two url parameters as equal even though they are equal

Time:08-29

I am using React.js and trying to filter store products based on the parameters that the user has chosen from a set of . When clicking on an input, "onChange" fires a function that takes the name and the value, encodes it, and puts it into the URL search query as a key/value pair.

Everything is working fine, except in one instance. When the user changes their mind and picks a different answer in the , my javascript code is supposed to:

  1. Get the current URL parameters,
  2. Check if the name is already in the URL param as a key,
  3. If it already is inside the URL param, don't add a new param, instead change the value of the key,
  4. Take the new set of URL parameters and use those instead.

The good news is that this works for most key/pairs. For example:

  1. { Color: #fffff } would look like this in the URL "?Color=#FFFFFF". If the user changed the color the URL parameter also changed.

But...

  1. I have a name "WITH USB 3 PORTS" that looks like this, when added to the URL param - "?With%20USB%203%20ports=Yes" , but when I try to change the value to "No" in the for some reason my javascript thinks that "With%20USB%203%20ports" is not the same as "With%20USB%203%20ports". It does not do this for "Color" or any other key/value pair.

Can anyone explain why this might be the case and how to stop this from happening?

To give some more context, I use:

  1. window.location.search -> to get the URL params
  2. encodeURIComponent() -> to prepare the values to be used a key/value pairs
  3. new URLSearchParams() -> to create the new params
  4. window.location.href -> to refer the user to the new URL (I will later use history.pushState())

UPDATE #1

Based on @Cerbrus recommendation, I added the code that creates this issue.

    //* Change the url params when the user changes the filter inputs
    changeUrlParam = () => {

        //* Prepare localhost variable
            const baseUrl = 'http://localhost:3000'

        //* Get current path name
            const pathName = window.location.pathname;
        
        //* Get current url parameters if any
            const urlQuery = window.location.search;
            const pureParam = urlQuery.replace('?', '');

        //* Create a new param
            const params = urlQuery.length < 1 ? new URLSearchParams() : new URLSearchParams(pureParam);
    
        //* Prepare the value/key pair
            const key = encodeURIComponent('With Usb 3 Ports');
            const value = 'Yes';

        //* If the params - ARE NOT SET
            if(urlQuery.length < 1) {
                //* Apend new value to it
                    params.append(key, value);

        //* If the params - ARE SET
            } else {
                //* Check if the param in question is already set
                    const paramTest = urlQuery.includes(key);

                //* If present - change it
                    if(paramTest === true) { 
                        //* Change the old value to the new value
                            params.set(key, value);
                //* If not present - apend it
                    } else {
                        //* Add the new value to the exsisting param
                            params.append(key, value);
                    }
            }

        //* Prepare the new url
            const newUrl = baseUrl   pathName   '?'   params.toString();
    
        //* Go to the new url
            return window.location.href = newUrl;
    };

CodePudding user response:

I think you're overcomplicating things.

  • URLSearchParams deals with decoding and encoding strings by itself, so doing encodeURIComponent confuses it (indeed, a double-encoded URI component isn't the same as the non-encoded one)
  • The whole exists/set/append thing seems to be a no-op; just set the single value you need.

Here's a standalone function; replace the search argument in the invocation(s) with window.location.search when you'd use it in your component.

function mangleParams(search, key, value) {
  const params = new URLSearchParams(search.replace(/^\?/, ''));
  params.set(key, value);
  return params.toString();
}

console.log(mangleParams('', 'With USB 3 ports', 'No'));
console.log(mangleParams('?With USB 3 ports=Yes', 'With USB 3 ports', 'Heck yeah'));
console.log(mangleParams('?With USB 3 ports=Yes&Other feature=Sure', 'With USB 3 ports', 'Nice'));

This outputs

With USB 3 ports=No
With USB 3 ports=Heck yeah
With USB 3 ports=Nice&Other feature=Sure

(so the s are also normalized to es, and all encoding works as it should).

  • Related