Categories
JavaScript

Common JavaScript Mistakes — Part 3

JavaScript is a language that’s friendlier than many other programming languages in the world. However, it’s still very easy to make mistakes when writing JavaScript code through misunderstanding or overlooking stuff that we already know. By avoiding some of the mistakes below, we can make our lives easier by preventing bugs and typos in our code that bog us down with unexpected results.


Trying to Overload Functions

Functional overloading is a feature of some programming languages where you can declare functions with the same name but different signatures. In JavaScript, we can’t overload functions. Whenever a function is declared more than once, the one that is declared later overwrites the one that’s declared earlier. This is because functions are objects and declaring a function is like assigning an object to a variable. When you assign an object to a variable more than once, then the value that’s assigned later will overwrite the value that’s assigned earlier. That means that we can’t have two functions with the same name in the same module in JavaScript. For example, if we have the following,

function add(a, b, c) {  
  return a + b + c;  
}

function add(a, b) {  
  return a + b;  
}

console.log(add(1, 2, 3));

then we get three because the add function that’s declared later has overwritten the one that’s declared earlier. To fix this, we have to rename one of them. We can also put them inside two different objects. Then they can have the same name since they aren’t in the same level. Also, we can write an Immediately Invoked Function Expression, or IIFE for short. IIFEs are run as soon as they’re defined. To wrap them in an object, we can write the following:

const a = {  
  add(a, b, c) {  
    return a + b + c;  
  }  
}

const b = {  
  add(a, b) {  
    return a + b;  
  }  
}

console.log(a.add(1, 2, 3));  
console.log(b.add(1, 2, 3));

As we can see, if we run the code, then the console.log of the first one will be six and the second one will be three since a.add has three parameters and b.add has two.

We can also use an IIFE as in the following example:

const sum1 = (function add(a, b, c) {  
  return a + b + c;  
})(1, 2, 3);

const sum2 = (function add(a, b) {  
  return a + b;  
})(1, 2, 3);

console.log(sum1);  
console.log(sum2);

In the code above, we wrapped the function inside the parentheses and then called it immediately after it was defined. Then we assigned the returned result to a variable. After that, we get six and three as we wanted. Because we called each function immediately and returned the result, we get the right result since they didn’t overlap. It also means that they can’t be called again.


Missing Parameters

When we add a new parameter to a function, then we have to remember to pass in the extra argument in the function calls. Otherwise, there may be undefined errors. To avoid undefined parameters creating errors, we can either check for it in our function, or we can set a default value of the parameter. For example, if we have the following function

function addressFn(address, city, region) { ... }

and we want to add a countryparameter and we have other parts of our program calling the function above, then we can add a default parameter. We can do this by writing the following:

function addressFn(address, city, region, country = 'US') { ... }

This way, if the country argument didn’t get passed in, country will be set to 'US'.


Forgetting About the this Keyword

When we try to access some property from another property inside an object, we should use the this keyword to get the property’s value that we want. For example, if we have the following,

let obj = {  
  prop: "some text",  
  method() {  
    console.log(prop);  
  }  
};

obj.method();

we will get an Uncaught ReferenceError: prop is not defined error when we run the code above. This is because we forgot to put the this keyword before the prop variable. Instead, we need to write the following:

let obj = {  
  prop: "some text",  
  method() {  
    console.log(this.prop);  
  }  
};

obj.method();

When we run the code above, then we get 'some text', which is what we wanted.


Iterate Through the Object Keys

The for...in loop will loop through the keys of the current object as well as all the prototypes’ keys. This isn’t ideal for all situations. It’s also slower than the other ways of iterating through the keys of an object. With the for...in loop, we need to use the Object.hasOwnProperty function to check that the property is originally defined in the object. This makes the loop even slower. This is a problem if we have a large object with lots of properties. For example, if we have,

const parent = {  
  pa: 1,  
  pb: 2  
}  
let obj = Object.create(parent);obj.a = 1;  
obj.b = 2;  
obj.c = 3;  
obj.d = 4;  
obj.e = 5;

then the for...in loop will loop through all the properties of the parent and the properties added to obj. If we only want to loop through the properties in obj, then we have to loop using the hasOwnProperty function as in the following code:

for (const key in obj) {  
  if (obj.hasOwnProperty(key)) {  
    console.log(obj[key]);  
  }  
}

However, this is slower than the newer alternatives, which are Object.keys to get the keys of an object and Object.entries to get the key-value pairs of an object. Then we loop through them with the for...of loop since both return arrays. They only loop through the object’s properties and nothing up the prototype chain. The fastest ways to loop through the entries are these two functions. We can use them as follows:

const parent = {  
  pa: 1,  
  pb: 2  
}  
let obj = Object.create(parent);obj.a = 1;  
obj.b = 2;  
obj.c = 3;  
obj.d = 4;  
obj.e = 5;for (const key of Object.keys(obj)) {  
  console.log(obj[key]);  
}

for (const [key, value] of Object.entries(obj)) {  
  console.log(value);  
}

In each example, we get the following logged,

a 1  
b 2  
c 3  
d 4  
e 5

which means that we’re getting what we want from the Object.keys and Object.entries functions.


Even though JavaScript is a friendly language, it’s still very easy to make mistakes when writing JavaScript code. Remember that in JavaScript, we can’t overload functions, so we can’t define two functions with the same name in the same level. If there’s potential for a function parameter to not be set, then we can set a default parameter so that it will never be undefined. Also, we can’t forget about the this object when we’re accessing one property from another property of the same object. Finally, we shouldn’t use the for...in loop anymore to loop through the keys of an object because it’s slow and clunky if we just want to loop through the keys of the current object without its prototype’s keys. We want to use the Object.keys or Object.entries functions instead so we get the keys or the key-value pairs, respectively, as arrays, and we can loop through them like any other array.

Categories
NativeScript React

NativeScript React — List Views

React is an easy to use framework for building front end apps.

NativeScript is a mobile app framework that lets us build native mobile apps with popular front end frameworks.

In this article, we’ll look at how to build an app with NativeScript React.

ListView

We can add a vertically scrolling list with the ListView component.

For example, we can write:

import * as React from "react";
import { ListView } from "react-nativescript";
import { ItemEventData } from "@nativescript/core";

type MyItem = { text: string };

const items: MyItem[] = [
  { text: 'apple' },
  { text: 'orange' },
  { text: 'grape' },
]

const cellFactory = (item: MyItem) => {
  return <label text={item.text} />;
};

const onItemTap = ({ index }: ItemEventData) => {
  const { text }: MyItem = items[index];
  console.log(`Tapped item index ${index}: "${text}".`);
};

export default function Greeting({ }) {
  return (
    <frame>
      <page>
        <actionBar title="Default Page Title" />
        <flexboxLayout justifyContent='center' >
          <ListView
            items={items}
            cellFactory={cellFactory}
            onItemTap={onItemTap}
          />
        </flexboxLayout>
      </page>
    </frame>
  );
}

We add the ListView with the items prop to add the items we want to display.

cellFactory is a function that returns the component with the row.

And onItemTap is the event handler that’s run when we tap on a row.

In the onItemTap function, we get the index of the item that we tapped on.

So we can get the item from that.

Using ListView with Multiple Templates

We can add ListView with multiple templates.

For example, we can write:

import * as React from "react";
import { ListView } from "react-nativescript";

type MyEvenItem = { textEven: string };
type MyOddItem = { textOdd: string };
type MyItem = MyEvenItem | MyOddItem;

const items: MyItem[] = [{ textEven: "apple" }, { textOdd: "orange" }];

function itemTemplateSelector(index): string {
  return index % 2 === 0 ? "even" : "odd";
}

const evenCellFactory = (item: MyEvenItem) => {
  return <label text={item.textEven} color="green" />;
};

const oddCellFactory = (item: MyOddItem) => {
  return <label text={item.textOdd} color="orange" />;
};

const cellFactories = new Map([
  [
    "odd",
    {
      placeholderItem: {
        text: "some odd text"
      },
      cellFactory: oddCellFactory
    }
  ],

[
    "even",
    {
      placeholderItem: {
        text: "some even text"
      },
      cellFactory: evenCellFactory
    }
  ],
]);

const onItemTap = (args) => {
  const index: number = args.index;
  const item: MyItem = items[index];
  const isEven: boolean = itemTemplateSelector(index) === "even";
  const itemText: string = isEven ?
    (item as MyEvenItem).textEven :
    (item as MyOddItem).textOdd;

console.log(`Tapped item index ${index} (${isEven ? "even" : "odd"}): "${itemText}".`);
};

export default function Greeting({ }) {
  return (
    <frame>
      <page>
        <actionBar title="Default Page Title" />
        <flexboxLayout justifyContent='center' >
          <ListView
            items={items}
            itemTemplateSelector={itemTemplateSelector}
            cellFactories={cellFactories}
            onItemTap={onItemTap}
          />
        </flexboxLayout>
      </page>
    </frame>
  );
}

We have the type annotations for the different types of items with the type declarations.

Then we have the itemTemplateSelector function to get the type of item displayed.

Next, we have the eventCellFactory and oddCellFactory functions to return the items that we want to display for the rows for each kind of item.

Then we add a Map to render each kind of item.

Next, we have the onItemTap function to log the item we tapped on.

And in Greeting , we have the ListView with the items prop to set the items we display.

itemTemplateSelector sets the template we want to use.

cellFactories sets the functions we want to use to render the rows.

onItemTap lets us render the rows.

Conclusion

We can add list views to add various kinds of data in our mobile app with React NativeScript.

Categories
NativeScript React

NativeScript React — HTML, Images, and Text

React is an easy to use framework for building front end apps.

NativeScript is a mobile app framework that lets us build native mobile apps with popular front end frameworks.

In this article, we’ll look at how to build an app with NativeScript React.

HtmlView

We can add the HtmlView component to display static HTML content.

For instance, we can write:

import * as React from "react";

export default function Greeting({ }) {
  return (
    <frame>
      <page>
        <actionBar title="Default Page Title" />
        <flexboxLayout justifyContent='center' >
          <htmlView html="<div><h1>hello world</h1></div>" />
        </flexboxLayout>
      </page>
    </frame>
  );
}

We set the html prop to the HTML string we want to render.

Then it’ll be displayed in our app.

Image

We can display images with the image component.

For instance, we can write:

import * as React from "react";

export default function Greeting({ }) {
  return (
    <frame>
      <page>
        <actionBar title="Default Page Title" />
        <flexboxLayout justifyContent='center' >
          <image src="~/assets/pic.jpg" stretch="none" />
        </flexboxLayout>
      </page>
    </frame>
  );
}

Then we display the pic.jpg image in the /src/assets folder.

We can display an image from a URL.

To do this, we write:

import * as React from "react";

export default function Greeting({ }) {
  return (
    <frame>
      <page>
        <actionBar title="Default Page Title" />
        <flexboxLayout justifyContent='center' >
          <image src="https://i.picsum.photos/id/20/200/200.jpg?hmac=wHmtG3BEC6aOsGZU_Q2wnxVQq34B__t4x4LFw-sptM8" stretch="none" />
        </flexboxLayout>
      </page>
    </frame>
  );
}

to set the src prop to the URL of an image.

Also, we can display an icon by writing:

import * as React from "react";

export default function Greeting({ }) {
  return (
    <frame>
      <page>
        <actionBar title="Default Page Title" />
        <flexboxLayout justifyContent='center' >
          <image src="res://icon" stretch="none" />
        </flexboxLayout>
      </page>
    </frame>
  );
}

We can also display an base64 image string by writing:

import * as React from "react";

export default function Greeting({ }) {
  return (
    <frame>
      <page>
        <actionBar title="Default Page Title" />
        <flexboxLayout justifyContent='center' >
          <image src="data:image/jpeg;base64,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" stretch="none" />
        </flexboxLayout>
      </page>
    </frame>
  );
}

Label

The label component lets us display read-only text.

For example, we can write:

import * as React from "react";

export default function Greeting({ }) {
  return (
    <frame>
      <page>
        <actionBar title="Default Page Title" />
        <flexboxLayout justifyContent='center' >
          <label>This is a Label</label>
        </flexboxLayout>
      </page>
    </frame>
  );
}

to display text on our screen.

To display formatted text, we use the formattedString and span components:

import * as React from "react";
import { Color } from "@nativescript/core";

export default function Greeting({ }) {
  return (
    <frame>
      <page>
        <actionBar title="Default Page Title" />
        <flexboxLayout justifyContent='center' >
          <label textWrap>
            <formattedString>
              <span>This text has a </span>
              <span color={new Color("red")}>red </span>
              <span>piece of text. </span>
              <span fontStyle="italic">This is italic, </span>
              <span fontWeight="bold">and this bit is bold.</span>
            </formattedString>
          </label>
        </flexboxLayout>
      </page>
    </frame>
  );
}

We put all our formatted text in the formattedString component.

The span have the text we want to display.

We style the text with props. The color prop takes an object returned by the Color function.

Conclusion

We can add HTML, images, and text to our mobile app with React NativeScript.

Categories
NativeScript React

NativeScript React — Action Items, Button, Date Pickers, and Frames

React is an easy to use framework for building front end apps.

NativeScript is a mobile app framework that lets us build native mobile apps with popular front end frameworks.

In this article, we’ll look at how to build an app with NativeScript React.

ActionItem

We can add the actionItem component to add buttons into the actionBar component.

For example, we can write:

import * as React from "react";

export default function Greeting({ }) {
  const onTapShare = () => console.log('tap share')
  const onTapDelete = () => console.log('tap delete')
  return (
    <frame>
      <page>
        <actionBar>
          <actionItem
            nodeRole="actionItems"
            onTap={onTapShare}
            android={{
              systemIcon: "ic_menu_share" as const,
              position: "actionBar" as const
            }}
          />
          <actionItem
            nodeRole="actionItems"
            onTap={onTapDelete}
            android={{
              systemIcon: "" as const,
              position: "popup" as const
            }}
            text="delete"
          />
        </actionBar>
        <flexboxLayout justifyContent='center'>
        </flexboxLayout>
      </page>
    </frame>
  );
}

We add the actionItem with the onTap prop to listen for taps on the item.

The android prop sets the icon for the action item and the position.

systemIcon sets the icon.

position sets the location of the action item.

'popup' will put it on a menu.

The text prop is the text of the popup menu item.

We can set the visibility prop to make an item visible or not.

To do this, we write:

import * as React from "react";

export default function Greeting({ }) {
  const [isEditing, setIsEditing] = React.useState(true)
  const onTapEdit = () => setIsEditing(isEditing => !isEditing)
  const onTapSave = () => setIsEditing(isEditing => !isEditing)
  return (
    <frame>
      <page>
        <actionBar>
          <actionItem
            nodeRole={"actionItems"}
            onTap={onTapEdit}
            visibility={isEditing ? "hidden" : "visible"}
            android={{
              systemIcon: "ic_menu_edit",
              position: "actionBar" as const
            }}
          />
          <actionItem
            nodeRole={"actionItems"}
            onTap={onTapSave}
            visibility={isEditing ? "visible" : "hidden"}
            android={{
              systemIcon: "ic_menu_save",
              position: "actionBar" as const
            }} />
        </actionBar>
        <flexboxLayout justifyContent='center'>
        </flexboxLayout>
      </page>
    </frame>
  );
}

We set the isEditing state to pick which icon is displayed.

Is the visbility prop is set to 'visible' , then it’s displayed.

Button

We can add a button with the button component.

For instance, we can write:

import * as React from "react";
import { EventData } from "[@nativescript/core](https://medium.com/r/?url=http%3A%2F%2Ftwitter.com%2Fnativescript%2Fcore "Twitter profile for @nativescript/core")";

export default function Greeting({ }) {
  return (
    <frame>
      <page>
        <flexboxLayout justifyContent='center' flexDirection="column">
          <button
            text="Button"
            onTap={({ object }: EventData) => {
              console.log(object);
            }}
          />
        </flexboxLayout>
      </page>
    </frame>
  );
}

We add the button with the text prop to set the button text.

The onTap prop takes a function that has the event data as the parameter.

The object property has the button that we clicked on.

DatePicker

We can add a DatePicker component to add a date picker to our app.

For instance, we can write:

import * as React from "react";

export default function Greeting({ }) {
  return (
    <frame>
      <page>
        <flexboxLayout justifyContent='center' flexDirection="column">
          <datePicker
            date={new Date()}
            onDateChange={({ value }) => {
              console.log(value)
            }}
          />
        </flexboxLayout>
      </page>
    </frame>
  );
}

We add the date picker with the datePicker component.

Then we listen for the date picker value changes with the onDateChange prop.

We get the latest selected date with the value property of the parameter.

Frame

We add the frame component to display page components.

Every app needs at least one frame element.

For example, we can use it by writing:

import * as React from "react";

export default function Greeting({ }) {
  return (
    <frame>
      <page>
        <actionBar title="Default Page Title" />
        <flexboxLayout justifyContent='center' >
          <label text="Default Page Content" />
        </flexboxLayout>
      </page>
    </frame>
  );
}

We add the page component in the frame .

Then we can add anything into the page component.

Conclusion

We can add items to action bars, buttons, date pickers, and frames as containers for content into our mobile app with React NativeScript.

Categories
NativeScript React

NativeScript React — WrapLayout, Activity Indicator, and Action Bar

React is an easy to use framework for building front end apps.

NativeScript is a mobile app framework that lets us build native mobile apps with popular front end frameworks.

In this article, we’ll look at how to build an app with NativeScript React.

WrapLayout

The wrapLayout component is a layout container that lets us position items in rows or columns.

For instance, we can write:

import * as React from "react";

export default function Greeting({ }) {
  return (
    <wrapLayout backgroundColor="#3c495e">
      <label
        text="first"
        width="30%"
        height="30%"
        backgroundColor="red"
      />
      <label
        text="second"
        width="30%"
        height="30%"
        backgroundColor="green"
      />
      <label
        text="third"
        width="30%"
        height="30%"
        backgroundColor="blue"
      />
      <label
        text="fourth"
        width="30%"
        height="30%"
        backgroundColor="yellow"
      />
    </wrapLayout>
  );
}

We add the label s inside the wrapLayout .

Then the 4th label will be displayed in the 2nd row since it overflows the first row.

We can make items wrap vertically with:

import * as React from "react";

export default function Greeting({ }) {
  return (
    <wrapLayout orientation="vertical" backgroundColor="#3c495e">
      <label
        text="first"
        width="30%"
        height="30%"
        backgroundColor="red"
      />
      <label
        text="second"
        width="30%"
        height="30%"
        backgroundColor="green"
      />
      <label
        text="third"
        width="30%"
        height="30%"
        backgroundColor="blue"
      />
      <label
        text="fourth"
        width="30%"
        height="30%"
        backgroundColor="yellow"
      />
    </wrapLayout>
  );
}

We have the orientation prop set to 'vertical' , so the 4th label will be added to the 2nd row.

ActivityIndicator

The ActivityIndicator component shows a progress indicator to tell the user of something running in the background.

For example, we can write:

import * as React from "react";

export default function Greeting({ }) {
  return (
    <flexboxLayout justifyContent='center'>
      <activityIndicator busy />
    </flexboxLayout>
  );
}

to add the activityIndicator .

When busy is true , then the loading indicator will display.

ActionBar

The actionBar component lets us show a toolbar at the top of the activity window.

For example, we can write:

import * as React from "react";

export default function Greeting({ }) {
  return (
    <frame>
      <page>
        <actionBar title="Default Page Title" />
        <flexboxLayout justifyContent='center'>
        </flexboxLayout>
      </page>
    </frame>
  );
}

We add the actionBar inside the frame and page components.

Then the title value will be displayed at the top.

We can add more content to the actionBar .

For example, we can write:

import * as React from "react";

export default function Greeting({ }) {
  return (
    <frame>
      <page>
        <actionBar>
          <stackLayout nodeRole={"titleView"} orientation="horizontal">
            <image src="res://icon" width={40} height={40} verticalAlignment="middle" />
            <label text="NativeScript" fontSize={24} verticalAlignment="middle" />
          </stackLayout>
        </actionBar>
        <flexboxLayout justifyContent='center'>
        </flexboxLayout>
      </page>
    </frame>
  );
}

We add the stackLayout and add the image and label inside.

And then we display the flexboxLayout below it to display the content.

We can remove the app border with the flat prop:

import * as React from "react";

export default function Greeting({ }) {
  return (
    <frame>
      <page>
        <actionBar title="My App" flat />
        <flexboxLayout justifyContent='center'>
        </flexboxLayout>
      </page>
    </frame>
  );
}

And we can add buttons into the actionBar by writing:

import * as React from "react";

export default function Greeting({ }) {
  return (
    <frame>
      <page>
        <actionBar>
          <label nodeRole={"titleView"}>Hello World</label>
          <actionItem nodeRole={"actionItems"}>
            <button nodeRole={"actionView"}>One</button>
          </actionItem>
          <actionItem nodeRole={"actionItems"}>
            <button nodeRole={"actionView"}>Two</button>
          </actionItem>
          <actionItem nodeRole={"actionItems"}>
            <button nodeRole={"actionView"}>Three</button>
          </actionItem>
        </actionBar>
        <flexboxLayout justifyContent='center'>
        </flexboxLayout>
      </page>
    </frame>
  );
}

We add the button s into actionItem s to add display them in the app bar.

Conclusion

We can add a wrap layout, activity indicator, and action bar into our mobile app with React NativeScript.