Categories
JavaScript JavaScript Basics

How to Repeat Strings with JavaScript

There are a few ways to repeat a string in JavaScript. JavaScript strings have a built in repeat() function. You can also use a loop to do the same thing.

String.repeat Function

To use the repeat function, you pass in the number of times you want to repeat the string as an argument. It returns a new string

For example:

const hello = "hello";  
const hello5 = A.repeat(5);  
console.log(hello5); // "hellohellohellohellohello"

Use a loop

You can use for loop and while loop to do repeatedly concatenate strings.

Using a for loop, you can do:

const hello = "hello";  
let hello5 = '';  
for (let i = 1; i <= 5; i++){  
  hello5 += hello;  
}  
console.log(hello5); // "hellohellohellohellohello"

With a while loop, you can do:

const hello = "hello";  
let hello5 = '';  
let i = 1;  
while(i <= 5){  
  hello5 += hello;  
  i++  
}  
console.log(hello5); // "hellohellohellohellohello"

They both involve increment indexes up to the maximum.

Categories
JavaScript React

How to Build Ionic Apps with React

With the latest version of the Ionic framework, a tool that lets you write mobile apps with web technologies, you can use React to build your mobile application. Before v4, Ionic only provided components for Angular, but now React has complete support for the components.

Ionic 4 is a mobile app framework and a component library. You can build mobile apps, progressive web apps, and normal web apps. The component library can also be used on its own. Of course, the hardware support remains in place for you to use if you wish.

The full reference for the React version of Ionic is at https://ionicframework.com/docs.

In this article, we will build a React web app with Ionic that does currency conversion. The home page will display the list of the latest exchange rates and another page will have a form to convert the currencies of your choice. To get the data, we use the Foreign exchange rates API located at https://exchangeratesapi.io/. We use the Open Exchange Rates API located at https://openexchangerates.org/ to get the list of currencies.

Getting Started

To start, we will install the Ionic CLI. We run:

npm install -g ionic@latest

Next, we run:

ionic start currency-converter --type=react

Then we select the Sidenav option to create an Ionic project with a left sidebar.

We will also need to install some other packages. We need Axios to make HTTP requests and MobX for state management. Run npm i axios mobx mobx-react in our project folder to install them.

Now we are ready to create some pages. In the pages folder, create ConvertCurrencyPage.jsx and add:

import {
  IonButtons,
  IonContent,
  IonHeader,
  IonItem,
  IonList,
  IonMenuButton,
  IonPage,
  IonTitle,
  IonToolbar,
  IonInput,
  IonLabel,
  IonSelect,
  IonSelectOption,
  IonButton
} from "@ionic/react";
import React from "react";
import { observer } from "mobx-react";
import { getExchangeRates } from "../requests";
const ConvertCurrencyPage = ({ currenciesStore }) => {
  const [fromCurrencies, setFromCurrencies] = React.useState({});
  const [toCurrencies, setToCurrencies] = React.useState({});
  const [values, setValues] = React.useState({ amount: 0 } as any);
  const [submitting, setSubmitting] = React.useState(false);
  const [toAmount, setToAmount] = React.useState(0);
const convertCurrency = async () => {
    setSubmitting(true);
    if (values.amount <= 0 || !values.from || !values.to) {
      return;
    }
    const { data } = await getExchangeRates(values.from);
    const rate = data.rates[values.to];
    setToAmount(values.amount * rate);
  };

  React.useEffect(() => {
    const fromCurrencies = {};
    for (let key in currenciesStore.currencies) {
      if (key != values.to) {
        fromCurrencies[key] = currenciesStore.currencies[key];
      }
    }
    setFromCurrencies(fromCurrencies);

  const toCurrencies = {};
    for (let key in currenciesStore.currencies) {
      if (key != values.from) {
        toCurrencies[key] = currenciesStore.currencies[key];
      }
    }
    setToCurrencies(toCurrencies);
  }, [currenciesStore.currencies, values.from, values.to]);

  return (
    <IonPage>
      <IonHeader>
        <IonToolbar>
          <IonButtons slot="start">
            <IonMenuButton />
          </IonButtons>
          <IonTitle>Convert Currency</IonTitle>
        </IonToolbar>
      </IonHeader>
      <IonContent>
        <IonList lines="none">
          <IonItem>
            <IonInput
              type="number"
              value={values.amount}
              color={!values.amount && submitting ? "danger" : undefined}
              min="0"
              onIonChange={ev =>
                setValues({ ...values, amount: (ev.target as any).value })
              }
            ></IonInput>
          </IonItem>
          <IonItem>
            <IonLabel>Currency to Convert From</IonLabel>
            <IonSelect
              placeholder="Select One"
              color={!values.from && submitting ? "danger" : undefined}
              onIonChange={ev =>
                setValues({ ...values, from: (ev.target as any).value })
              }
            >
              {Object.keys(fromCurrencies).map(key => {
                return (
                  <IonSelectOption value={key} key={key}>
                    {(fromCurrencies as any)[key]}
                  </IonSelectOption>
                );
              })}
            </IonSelect>
          </IonItem>
          <IonItem>
            <IonLabel>Currency to Convert To</IonLabel>
            <IonSelect
              placeholder="Select One"
              color={!values.to && submitting ? "danger" : undefined}
              onIonChange={ev =>
                setValues({ ...values, to: (ev.target as any).value })
              }
            >
              {Object.keys(toCurrencies).map(key => {
                return (
                  <IonSelectOption value={key} key={key}>
                    {(toCurrencies as any)[key]}
                  </IonSelectOption>
                );
              })}
            </IonSelect>
          </IonItem>
          <IonItem>
            <IonButton size="default" fill="solid" onClick={convertCurrency}>
              Convert
            </IonButton>
          </IonItem>
          {toAmount ? (
            <IonItem>
              {values.amount} {values.from} is {toAmount} {values.to}.
            </IonItem>
          ) : (
            undefined
          )}
        </IonList>
      </IonContent>
    </IonPage>
  );
};
export default observer(ConvertCurrencyPage);

This adds a form to convert currency from one to another. In this form, we filter by choices by excluding from the currency being converted to from the first drop down and exclude the currency being converted from in the second dropdown. Also, we have an ion-input for the amount being converted. We get the values of the currency from the currenciesStore, which is the MobX store that gets the list of currencies from. In the IonSelect components we set the onIonChange props to the handler functions that set the drop down’s values. We also set the placeholder for all the inputs and selects. In the IonInput component, we do the same with the onIonChange handler. We show the correct value by using the variables set in the values object during change events.

When the user clicks Convert, we run the convertCurrency function. We check if the values are set correctly before running the rest of the code. If that succeeds, then we run the getExchangeRates function imported from requests.js, then we set the final toAmount by multiplying the rate with the amount.

The useEffect callback is used for excluding the currency to convert from the currency to convert to list and vice versa. The array in the second argument useEffect specifies which values to watch for.

The observer function in the last line is for designating the component to watch the latest values from the MobX stores.

Next in Home.tsx, we replace the existing code with:

import {
  IonButtons,
  IonContent,
  IonHeader,
  IonItem,
  IonLabel,
  IonList,
  IonListHeader,
  IonMenuButton,
  IonPage,
  IonTitle,
  IonToolbar,
  IonSelect,
  IonSelectOption
} from "@ionic/react";
import React from "react";
import "./Home.css";
import { getExchangeRates } from "../requests";
import { CurrencyStore } from "../stores";
import { observer } from "mobx-react";
const HomePage = ({ currencyStore, currenciesStore }) => {
  const [rates, setRates] = React.useState({});
  const getRates = async () => {
    const { data } = await getExchangeRates(
      (currencyStore as CurrencyStore).currency
    );
    setRates(data.rates);
  };

  React.useEffect(() => {
    getRates();
  }, [(currencyStore as CurrencyStore).currency]);
  return (
    <IonPage>
      <IonHeader>
        <IonToolbar>
          <IonButtons slot="start">
            <IonMenuButton />
          </IonButtons>
          <IonTitle>Home</IonTitle>
        </IonToolbar>
      </IonHeader>
      <IonContent>
        <IonList lines="none">
          <IonListHeader>Latest Exchange Rates</IonListHeader>
          <IonItem>
            <IonLabel>Currency</IonLabel>
            <IonSelect
              placeholder="Select One"
              onIonChange={ev => {
                (currencyStore as CurrencyStore).setCurrency(
                  ev.target && (ev.target as any).value
                );
              }}
            >
              {Object.keys(currenciesStore.currencies).map(key => {
                return (
                  <IonSelectOption
                    value={key}
                    key={key}
                    selected={
                      (currencyStore as CurrencyStore).currency
                        ? key == (currencyStore as CurrencyStore).currency
                        : key == "AUD"
                    }
                  >
                    {(currenciesStore.currencies as any)[key]}
                  </IonSelectOption>
                );
              })}
            </IonSelect>
          </IonItem>
        </IonList>
        <IonList lines="none">
          <IonListHeader>Exchange Rates</IonListHeader>
          {Object.keys(rates).map(key => {
            console.log(rates);
            return (
              <IonItem>
                {key}: {rates[key]}
              </IonItem>
            );
          })}
        </IonList>
      </IonContent>
    </IonPage>
  );
};
export default observer(HomePage);

In this file, we display the exchange rates from an API. We get the currencies from the currenciesStore so that users can see exchange rates based on different currencies. The items are displayed in an IonList provided by Ionic.

The observer function in the last line is for designating the component to watches the latest values from the MobX stores.

Next in App.tsx, replace the following code with:

import React from "react";
import { Redirect, Route } from "react-router-dom";
import { IonApp, IonRouterOutlet, IonSplitPane } from "@ionic/react";
import { IonReactRouter } from "@ionic/react-router";
import { AppPage } from "./declarations";
import Menu from "./components/Menu";
import Home from "./pages/Home";
import { home, cash } from "ionicons/icons";
/* Core CSS required for Ionic components to work properly */
import "@ionic/react/css/core.css";
/* Basic CSS for apps built with Ionic */
import "@ionic/react/css/normalize.css";
import "@ionic/react/css/structure.css";
import "@ionic/react/css/typography.css";
/* Optional CSS utils that can be commented out */
import "@ionic/react/css/padding.css";
import "@ionic/react/css/float-elements.css";
import "@ionic/react/css/text-alignment.css";
import "@ionic/react/css/text-transformation.css";
import "@ionic/react/css/flex-utils.css";
import "@ionic/react/css/display.css";
/* Theme variables */
import "./theme/variables.css";
import ConvertCurrencyPage from "./pages/ConvertCurrencyPage";
import { CurrencyStore, CurrenciesStore } from "./stores";
import { getCurrenciesList } from "./requests";
const currencyStore = new CurrencyStore();
const currenciesStore = new CurrenciesStore();
const appPages: AppPage[] = [
  {
    title: "Home",
    url: "/home",
    icon: home
  },
  {
    title: "Convert Currency",
    url: "/convertcurrency",
    icon: cash
  }
];
const App: React.FC = () => {
  const [initialized, setInitialized] = React.useState(false);
  const getCurrencies = async () => {
    const { data } = await getCurrenciesList();
    currenciesStore.setCurrencies(data);
    setInitialized(true);
  };
  React.useEffect(() => {
    if (!initialized) {
      getCurrencies();
    }
  });
  return (
    <IonApp>
      <IonReactRouter>
        <IonSplitPane contentId="main">
          <Menu appPages={appPages} />
          <IonRouterOutlet id="main">
            <Route
              path="/home"
              render={() => (
                <Home
                  currencyStore={currencyStore}
                  currenciesStore={currenciesStore}
                />
              )}
              exact={true}
            />
            <Route
              path="/convertcurrency"
              render={() => (
                <ConvertCurrencyPage
                  currenciesStore={currenciesStore}
                />
              )}
              exact={true}
            />
            <Route exact path="/" render={() => <Redirect to="/home" />} />
          </IonRouterOutlet>
        </IonSplitPane>
      </IonReactRouter>
    </IonApp>
  );
};
export default App;

We modified the routes so that we use the render prop instead of the component prop since we want to pass in our MobX stores into the components. The stores contain the currently selected currency for the home page and the list of currencies for both pages.

We get/set the list of currencies here for both components.

Next, create requests.ts in the src folder and add:

const axios = require('axios');
const APIURL = 'https://api.exchangeratesapi.io';
const OPEN_EXCHANGE_RATES_URL = 'http://openexchangerates.org/api/currencies.json';

export const getExchangeRates = (baseCurrency: string) => axios.get(`${APIURL}/latest?base=${baseCurrency}`)
export const getCurrenciesList = () => axios.get(OPEN_EXCHANGE_RATES_URL)

This the code for making the HTTP requests to get the currencies and exchange rates.

Next create store.ts and add:

import { observable, action } from "mobx";
class CurrencyStore {
    @observable currency: string = 'AUD';
    @action setCurrency(currency: string) {
        this.currency = currency;
    }
}
class CurrenciesStore {
    @observable currencies = {};
    @action setCurrencies(currencies) {
        this.currencies = currencies;
    }
}
export { CurrencyStore, CurrenciesStore };

The CurrencyStore is for storing the selected currency in the home page and to show the exchange rates based on the selected currency. currency is the value observed by the home page and setCurrency sets the currency value. Similarly, CurrenciesStore stores a list of currencies retrieved in App.tsx where setCurrencies is called.

Next in tsconfig.json, we replace the existing code with:

{
  "compilerOptions": {
      "experimentalDecorators": true,
    "target": "es5",
    "lib": [
      "dom",
      "dom.iterable",
      "esnext"
    ],
    "allowJs": true,
    "skipLibCheck": true,
    "esModuleInterop": true,
    "allowSyntheticDefaultImports": true,
    "strict": true,
    "forceConsistentCasingInFileNames": true,
    "module": "esnext",
    "moduleResolution": "node",
    "resolveJsonModule": true,
    "isolatedModules": true,
    "noEmit": true,
    "jsx": "preserve",
    "noImplicitAny": false
  },
  "include": [
    "src"
  ]
}

This changes noImplicitAny and sets it to true.

Categories
JavaScript

Using the URLSearchParams Object in JavaScript — Part 2

Working with query strings can be a pain if we have to write the code from scratch to parse and modify it. Fortunately, most recent browsers have the URLSearchParams object that can let us deal with query strings easily. With it, is makes it easy to parse and manipulate query strings. We no longer need a third party library or write code from scratch to deal with query strings anymore. In this article, we continue from part 1 of this guide.

We can create a URLSearchParams object with the URLSearchParams constructor. The URLSearchParams constructor takes one optional argument, which is a USVString argument that has the query string. USVString objects correspond to the set of all possible sequences of Unicode scalar values. In our code, we can treat them the same as regular strings. It can be a sequence of USVStrings or a record that contains USVStrings. In our code, we don’t have to concerned with USVStrings. For all practical purposes, they’re treated as like strings. We can construct a URLSearchParams object like the following code:

const url = new URL('https://example.com?key1=1&key2=2');
const params = new URLSearchParams(url.search);
console.log(params.get('key1'));
console.log(params.get('key2'));

There are other ways to create URLSearchParams object which involves passing in other kinds of objects. To see the details see the Part 1 of this guide.

More Methods

Each URLSearchParams instance has multiple methods available to it to get the keys and values and to manipulate them by adding, changing and removing keys or values. With these methods, we can construct query strings easily without having to do string manipulating directly. If we want to get back the full query string after manipulating, we can get it with the toString() method.

get

The get method of the URLSearchParams object let us get a value of the query string by the given key. It takes one argument, which is the string with the key name. It returns the USVString of the value if the search parameter is found, otherwise, it returns null . For example, if we have the following query string and URLSearchParams object like in the code below:

const url = new URL('https://example.com?key1=1&key2=2');
const params = new URLSearchParams(url.search);
console.log(params.get('key1'));

Then we get 1 from the console.log statement we have above. If we have more than one key-value pair with the same key like in the following example:

const url = new URL('https://example.com?key1=1&key2=2');
const params = new URLSearchParams(url.search);
params.append('key1', 2);
params.append('key1', 3);
console.log(params.get('key1'));

Then we get the first value that’s present as the value returned from the get method. If we want to get all the values associated with the given key, we can use the getAll method. It’s the same even if we didn’t use the append method to add more key-value pairs to the query string:

const url = new URL('https://example.com?key1=1&key1=2&key1=3&key2=2');
const params = new URLSearchParams(url.search);
console.log(params.get('key1'));

In the above example, we still get 1 from the console.log output above.

If we try to get a value with a key that didn’t exist, then we get null returned, like in the example below:

const url = new URL('https://example.com?key1=1&key2=2');
const params = new URLSearchParams(url.search);
console.log(params.get('abc'));

We get null from the console.log statement above since we don’t have a search parameter with the key 'abc' .

getAll

With the getAll method, we can get all the values with the associated key name. It takes one argument, which is a string with the key name and returns USVString array with all the values associated with the key name. For example, if we have the following code:

const url = new URL('https://example.com?key1=1&key2=2');
const params = new URLSearchParams(url.search);
params.append('key1', 2);
params.append('key1', 3);
console.log(params.getAll('key1'));

Then we get [“1”, “2”, “3”] from the console.log statement above.

has

The has method returns a boolean value that is true if the value with the given key exists. It takes one argument, which is a string with the key name that we want to look up. For example, we can use the has method like in the following code:

const url = new URL('https://example.com?key1=1&key2=2');
const params = new URLSearchParams(url.search);
params.append('key1', 2);
params.append('key1', 3);
console.log(params.has('key1'));
console.log(params.has('abc'));

When we run the code above, we get that the first console.log statement will output true while the second one will output false . This is what we expect since we have ‘key1’ as the key of one or more search parameters, but we don’t have any search parameter with 'abc' as the key.

keys

We can use the keys method to get an iterator which let us iterate through all the search parameter keys in our query string. The keys are all USVString objects. It takes no arguments and returns an iterator which let us iterate through the search parameter keys. For example, we can write:

const url = new URL('https://example.com?key1=1&key2=2');
const params = new URLSearchParams(url.search);
for (const key of params.keys()) {
  console.log(key);
}

Then we get the following out from the console.log statements above:

key1  
key2

set

The set method of the URLSeacrchParam instance let us set the value with the given search parameter key. It takes 2 arguments. The first is a string with the search parameter key, and the second is the value that you want to set as the value with the given key. If there’re several values with the same key, then they’ll be deleted. If the search parameter with the given key doesn’t exist, then this method will create it.

For example, we can use it like the following code:

const url = new URL('https://example.com?key1=1&key2=2');
const params = new URLSearchParams(url.search);
params.append('key1', 2);
params.append('key1', 3);
params.set('key1', 5);
console.log(params.getAll('key1'));
console.log(params.toString());

If we run the code above, will get the array[“5”] from the first console.log statement above. All the other values for key1 are removed as we expected. The second console.log statement will get us key1=5&key2=2 which matches what we have from the getAll method. We can also use it to create a new search parameter key-value pair, like we do with the following code:

const url = new URL('https://example.com?key1=1&key2=2');
const params = new URLSearchParams(url.search);
params.append('key1', 2);
params.append('key1', 3);
params.set('abc', 1);
console.log(params.getAll('abc'));
console.log(params.toString());

After we run the code above, we get back [“1”] from the first console.log statement, which means the search parameter with the key 'abc' and the value 1 is created, like we expected. The query string that we get when we use the toString() method is key1=1&key2=2&key1=2&key1=3&abc=1 , which is consistent with what we get from the getAll() method.

sort

We can sort the key-value pairs of a URLSearchParams object by its keys with the sort() method. The sort order is determined by the Unicode code points of the keys. The relative order between key-value pairs with the same keys will be preserved. This method takes no arguments and returns undefined . For instance, we can use it like in the following code:

const url = new URL('https://example.com?key1=1&key2=2');
const params = new URLSearchParams(url.search);
params.append('key1', 2);
params.append('key1', 3);
params.set('abc', 1);
params.sort();
console.log(params.toString());

If we run the code above, we get:

abc=1&key1=1&key1=2&key1=3&key2=2

from the console.log statement’s output, which is what we expect since 'abc' has lower code points than 'key1' and ‘key1' has lower code point value than ‘key2' .

toString

As we can see from the earlier examples, the toString() method returns the query string which we can put in a URL. The query string returned will be include the results after manipulation of the URLSearchParams object are done. Note that the returned query string will not have the question mark in front of it, unlike what’s returned from window.location.searh. For example, if we have:

const url = new URL('https://example.com?key1=1&key2=2');
const params = new URLSearchParams(url.search);
params.append('key3', 3);
params.append('key4', 4);
params.set('key5', 5);
console.log(params.toString());

Then we get back:

'key1=1&key2=2&key3=3&key4=4&key5=5'

Which is what we expected. We have all the search parameters we parsed from the URL object and whatever we append with the URLSearchParams object’s append() method and also what we added with the set() method.

values

The values method returns an iterator that let us iterate through all the values contained in the URLSearchParams object. Iterators can be iterated through by the for...of loop and operated on by the spread operator. It takes no arguments. For example, if we have the following code:

const url = new URL('https://example.com?key1=1&key2=2');
const params = new URLSearchParams(url.search);
params.append('key3', 3);
params.append('key4', 4);
params.set('key5', 5);
for (const value of params.values()) {
  console.log(value);
}

Then we get the following output from the console.log statements in the loop:

1  
2  
3  
4  
5

Which are the values that we set in the search parameters.

Catches When Using URLSearchParams Object

The URLSearchParams constructor can’t parse full URLs. So something like:

const params = new URLSearchParams('https://example.com?key1=1&key2=2');
for (const [key, value] of params.entries()) {
  console.log(key, value);
}

will not work. When we run the code above, we get the following outputs from the console.log statements:

https://example.com?key1 1
key2 2

As we can see, the whole URL before the first equal sign was parsed as the key of the first search parameter, which is wrong. This means that we have to use the URL object’s search property to get the query string and pass it in like we do in the example below:

const url = new URL('https://example.com?key1=1&key2=2');
const params = new URLSearchParams(url.search);
for (const [key, value] of params.entries()) {
  console.log(key, value);
}

If we run the code above, we get the following output from the console.log statements:

key1 1  
key2 2

The output above is what we want since these are the actual search parameter key-value pairs.

Most recent browsers have the URLSearchParams object that can let us deal with query strings easily. Now working with query strings is no longer a pain since we don’t have to write the code from scratch to parse and modify it. With URLSearchParams objects, is makes it easy to parse and manipulate query strings. We no longer need a third party library or write code from scratch to deal with query strings anymore. The only catch is that we have to pass in a query string to the constructor, or sequences like Maps and arrays with key-value pairs as an array with key as the first element and the value as the second element. See Part 1 for more details on how to construct URLSearchParams objects.

Categories
JavaScript

Using the URLSearchParams Object in JavaScript — Part 1

Working with query strings can be a pain if we have to write the code from scratch to parse and modify it. Fortunately, most recent browsers have the URLSearchParams object that can let us deal with query strings easily. With it, is makes it easy to parse and manipulate query strings. We no longer need a third party library or write code from scratch to deal with query strings anymore. In the part 1 of this guide, we will look at how to create URLSearchParams objects and look at a few handy methods which let us get and set key-value pairs of a query string.

Create URLSearchParam Objects

We can create a URLSearchParams object with the URLSearchParams constructor. The URLSearchParams constructor takes one optional argument, which is a USVString argument that has the query string. USVString objects correspond to the set of all possible sequences of Unicode scalar values. In our code, we can treat them the same as regular strings. It can be a sequence of USVStrings or a record that contains USVStrings. In our code, we don’t have to concerned with USVStrings. For all practical purposes, they’re treated as like strings. We can construct a URLSearchParams object like the following code:

const url = new URL('https://example.com?key1=1&key2=2');
const params = new URLSearchParams(url.search);
console.log(params.get('key1'));
console.log(params.get('key2'));

With the code above, we create a URL object, then we get the query string with the search property of the URL object, then we pass that into the URLSearchParams constructor. Then we can use the URLSearchParams object to get the value of the key using the get method of the URLSearchParams object. The console.log statements above should get us the values 1 and 2 respectively.

We can also constructor a URLSearchParams object using an array with entries that are arrays with the key as the first element and the value as the second element. For example, we can construct a URLSearchParams objects with arrays like in the following code:

const params = new URLSearchParams([
  ["key1", 1],
  ["key2", 2]
]);
console.log(params.get('key1'));
console.log(params.get('key2'));
console.log(params.toString());

With the code above, we pass in an array with the key and value in the entries. With the toString() instance method, we can get the full query string easily. The console.log statements above should get us the values 1 and 2 respectively with the first 2 statements and the last one should get us key1=1&key2=2 . Creating query strings have never been easier with this object.

A third way to construct a URLSearchParams object is with a plain JavaScript object passed into the constructor. The keys would be in the keys of the object, and the values are in the values of the object. For example, we can construct a URLSearchParams object like in the following code:

const params = new URLSearchParams({key1: 1, key2: 2});
console.log(params.get('key1'));
console.log(params.get('key2'));
console.log(params.toString());

The console.log statements above should get us the values 1 and 2 respectively with the first 2 statements and the last one should get us key1=1&key2=2 . Creating query strings have never been easier with this object.

We can also pass in Maps into the constructor and get back a query string. With Maps, we can pass it in like in the following code:

const params = new URLSearchParams(new Map([['key1', 1], ['key2', 2]]));
console.log(params.get('key1'));
console.log(params.get('key2'));
console.log(params.toString());

We should get the same output as the earlier examples with the console.log statements above.

After constructing a URLSearchParams object, we can iterate through it since it’s an array like object. An array like object are objects that have an iterator method included. The method is identified with the Symbol.iterator Symbol. We can iterate through the entries of an array like objects with the for...of loop. For example, if we have the following URLSearchParams object:

const url = new URL('https://example.com?key1=1&key2=2');
const params = new URLSearchParams(url.search);
for (const [key, value] of params) {
  console.log(key, value);
}

Then we get back the following console.log outputs:

key1 1  
key2 2

As we can see, we get back all the query string keys and values with with for...of loop. This is another reason to use the URLSearchParams object to parse query strings. It is an iterable object that lets us get the keys and values easily. This feature is even more useful is we have a long list of query string key-value pairs. Alternatively, we can use the entries method, which is an instance method of an URLSearchParams object. to get back the key-value pairs of a query string, like we do in the following code:

const url = new URL('https://example.com?key1=1&key2=2');
const params = new URLSearchParams(url.search);
for (const [key, value] of params.entries()) {
  console.log(key, value);
}

We should get back the same output as the first example with where we loop through the params object directly with the for...of loop.

Methods

Each URLSearchParams instance has multiple methods available to it to get the keys and values and to manipulate them by adding, changing and removing keys or values. With these methods, we can construct query strings easily without having to do string manipulating directly. If we want to get back the full query string after manipulating, we can get it with the toString() method.

append

The append method lets us add an key-value pair to the URLSearchParams object as a new search parameter. The method takes 2 arguments. One for the key name and one for the value. Both arguments will be converted to strings when we pass them in. We can append the same key multiple times with or without the same corresponding value. For example, we can use the append method like in the following code:

const url = new URL('https://example.com?key1=1&key2=2');
const params = new URLSearchParams(url.search);
params.append('key1', 1);
params.append('key1', 2);
console.log(params.toString());

With the code above, we should get back key1=1&key2=2&key1=1&key1=2 from the console.log statement we have in the code above. As we can see, we can append the same key-value pair as many times as we want and the append method will not attempt to merge them together.

delete

The delete method of the URLSearchParams object will let us delete the key-value pair with the given key. If there’s more than one with the same key, then they’ll all be deleted. If takes one argument, which is the key name as a string. For example, we can write the following code:

const url = new URL('https://example.com?key1=1&key2=2');
const params = new URLSearchParams(url.search);
params.append('key1', 1);
params.append('key1', 2);
params.delete('key1');
console.log(params.toString());

If we run console.log above like we did on the last of the code above, we get back key2=2 . This means that all the key-value pairs with key name key1 were removed from the URLSearchParams object and the corresponding query string.

entries

The entries method gets the key-value pairs from the URLSearchParams object. It takes no arguments and returns an iterator that let us iterate through the key-value pairs. The key-value pairs will be in the form of an array with the key as the first element and the corresponding value as the second element. For example, we can use the entries method like in the following code:

const url = new URL('https://example.com?key1=1&key2=2');
const params = new URLSearchParams(url.search);
for (const [key, value] of params.entries()) {
  console.log(key, value);
}

In the code above, we used the destructuring assignment syntax to decompose the key-value array into their own variables. This is a great way to access the keys and values since we don’t have to use the indexes or assign them to variables with our own code.

forEach

The forEach method let us iterate the values directly without using the entries method. It takes a callback function where can can access the key and value of each URLSearchParams entry. The callback function has the value as the first parameter and the key as the second parameter. For example, if we have the following code:

const url = new URL('https://example.com?key1=1&key2=2');
const params = new URLSearchParams(url.search);
params.append('key3', 3);
params.append('key4', 4);
params.append('key5', 5);
params.forEach((value, key) => {
  console.log(key, value);
})

When we run the code above, we should get the following output from the console.log statements:

key1 1  
key2 2  
key3 3  
key4 4  
key5 5

It’s important to note the value parameter comes before the key, so we don’t reverse them like in most other places.

There are more methods in the URLSearchParams object, we will continue the list of methods and look at the caveats for using the URLSearchParams objects in part 2 of this guide.

Most recent browsers have the URLSearchParams object that can let us deal with query strings easily. Now working with query strings is no longer a pain since we don’t have to write the code from scratch to parse and modify it. With URLSearchParams objects, is makes it easy to parse and manipulate query strings. We no longer need a third party library or write code from scratch to deal with query strings anymore. There are more methods in the URLSearchParams object and some caveats when using it, so stay tuned for Part 2.

Categories
JavaScript JavaScript Basics

How to Merge Arrays in JavaScript

Oftentimes, we need to combine multiple arrays into one array. With multiple arrays, combining them is pain without some help from JavaScript’s standard libraries. With ES6, there’s also the spread syntax to help us combine arrays.

There are a few ways to merge arrays in JavaScript.

Array.concat

We can all Array.concat on an array to combine 2 arrays and return the new one. For example:

const a = [1,2,3];
const b = [4,5];
const c = a.concat(b) // [1,2,3,4,5]

It also works with multiple arrays. You can pass in as many arrays as you want in the arguments of the concat function. For example:

const a = [1,2,3];
const b = [4,5];
const c = [6,7,8];
const d = a.concat(b, c) // [1,2,3,4,5,6,7]

Array.push

We can push elements of one array into another.

const a = [1,2,3];
const b = [4,5];
let c = Object.assign([], a);
for (let i = 0; i < b.length; i++){
  c.push(b[i]);
}
console.log(c); // [1,2,3,4,5]

What we did is make a copy of a and assigned it to c , then pushed the elements of b by looping through it and adding them to the end of c .

You can use the apply function available with all objects to combine 2 arrays. For example:

const a = [1,2];
const b = [3,4];
a.push.apply(a, b);
console.log(a); // [1,2,3,4];

Spread Operator

With ES6 or later, we can use the spread operator to spread the items from another array into a new array by doing the following:

const a = [1,2,3];
const b = [4,5];
const c = [...a, ...b];
console.log(c); // [1,2,3,4,5]