Categories
Uncategorized

How to work with dates and times in Swift 3, part 1: Dates, Calendars, and DateComponents

i just want to use dates

If you’re just getting started with date and time programming in Swift 3, chances are that you probably did some Googling, found something about NSDate and its companion classes in Apple’s documentation and promptly got confused. Let me reassure you that it isn’t your fault.

For starters, a lot of the documentation out there is in Objective-C, which can throw you off if you’re not familiar with its [instance method: parameter2: parameter3:] method-calling syntax. There’s also the fact that Apple recently removed the NS prefix from Cocoa’s class names — NSDate is now just plain ol’ Date, NSCalendar is now Calendar, NSDateComponents is now DateComponents, and so on. And finally, in the move towards protocol-oriented programming, Apple has changed some classes to structs, including many of the classes for working with dates and times.

And finally, if you’re coming to Swift 3 from JavaScript, which makes do with a single object type called Date, the idea of having this set of classes just to handle dates and times looks like overkill:

swift 3 date and time classes

Click the diagram to see it at full size.

In this series of articles, we’ll look at date and time programming in Swift 3. By its end, you’ll have a firm grasp on the topic.

Swift’s Date struct represents dates and times

swift date struct

Click the diagram to see it at full size.

In Swift, dates and times are represented by instances of Date, which is a struct. Date is independent of any time zone, or even any calendar system. It gets this independence through the way it represents time: as a number of seconds relative to the start of the Third Millennium, January 1, 2001, 00:00:00 UTC.

The following playground code shows the various ways of creating Dates:

// To create a Date representing the current date and time,
// simply initialize a new Date.
let now = Date()


// The other initializers expect arguments of type TimeInterval,
// which is a typealias for Double.


// To create a Date a specified number of seconds before or after
// the current date and time, use the "timeIntervalSinceNow" initializer.
let fiveMinutesAgo = Date(timeIntervalSinceNow: -5 * 60)
let fiveMinutesFromNow = Date(timeIntervalSinceNow: 5 * 60)


// To create a Date relative to Swift's reference date and time,
// use the "timeIntervalSinceReferenceDate" initializer.

// The first mobile phone call was made on April 3, 1973.
// We don't know the exact time the call was made, but it happened
// sometime during business hours in New York City, in the U.S. Eastern
// Time Zone. Noon that day was 875,602,800 seconds prior to the
// reference date and time.
let firstMobileCallDate = Date(timeIntervalSinceReferenceDate: -875_602_800)

// The "Stevenote" where the iPhone was introduced started on January 9, 2007,
// 10 a.m. Pacific time, 190,058,400 seconds after the reference date and time.
let iPhoneStevenoteDate = Date(timeIntervalSinceReferenceDate: 190_058_400)


// Unix time (a.k.a. POSIX time or Epoch Time) is the way time is represented
// by Unix, Unix-like, and other operating systems. It defines time as a 
// number of seconds after the Unix Epoch, January 1, 1970, 00:00:00 UTC.
// To create a Date relative to the Unix Epoch, use the 
// "timeIntervalSince1970" initializer.
let oneYear = TimeInterval(60 * 60 * 24 * 365)
let newYears1971 = Date(timeIntervalSince1970: oneYear)
let newYears1969 = Date(timeIntervalSince1970: -oneYear)


// To create a Date relative to another Date, use the
// "timeInterval:Since:" initializer.

// The "Stevenote" where the iPad was introduced started on January 27, 2010,
// 10 a.m. Pacific time, 96,249,600 seconds after the start of the iPhone Stevenote
// three years earlier.
let secondsBetweeniPhoneAndiPadStevenote = TimeInterval(96_249_600)
let iPadStevenoteDate = Date(timeInterval: secondsBetweeniPhoneAndiPadStevenote,
                             since: iPhoneStevenoteDate)

Of course, we don’t think of dates and times in terms of seconds relative to the start of the Third Millennium, or the start of the Unix Epoch, or any other arbitrary date and time. That’s why Swift features a couple of other structs to help us make sense of Dates: Calendar and DateComponents.

Calendars give dates context, DateComponents let us assemble dates or break dates apart

swift calendar struct

Click the diagram to see it at full size.

Think of the Calendar struct as a way to view Dates in a way that makes more sense to us: not as a number of seconds before or after January 1, 2001 00:00:00 UTC, but in terms of a year, month, day, hour, minute, and more.

The Calendar struct supports 16 different calendar systems, including the Gregorian calendar (a.k.a. the Western or Christian calendar), which is likely the one you use the most. Consider Swift’s reference date:

  • In a Date struct, its value is 0.
  • In the Gregorian calendar, this date has the following values:
    • Year: 2001
    • Month: 1
    • Day: 1
    • Hour: 0
    • Minute: 0
  • In the Hebrew calendar, this date has the following values:
    • Year: 5761
    • Month: 4
    • Day: 6
    • Hour: 0
    • Minute: 0
  • In the Buddhist calendar, this date has the following values:
    • Year: 2543
    • Month: 1
    • Day: 1
    • Hour: 0
    • Minute: 0

In most apps, you’ll likely be using the Gregorian calendar, so Calendar‘s real use is to convert Dates into DateComponents, and DateComponents into Dates:

swift datecomponents struct

Click the diagram to see it at full size.

The DateComponents struct is an assembly of properties that make up a date, such as year, month, date, hour, minute, second, and so on. DateComponents instances can be used to represent either a specific point in time, or a duration of time.

Using both Calendar and DateComponents structs, we can perform these key actions:

  • Build Dates using properties such as year, month, day, hour, and minute rather than a number of second relative to a reference date, and
  • extract properties from Dates, such as year, month, day, hour, and minute.

Let’s start creating some Dates with the help of Calendar and DateComponents.

Let’s create a Date given a year, month, and day, part 1

alexander graham bell

Let’s start with the first date in phone history: March 10, 1876, the day when Alexander Graham Bell made the first phone call. Create a new playground and enter or paste the code below:

// The user's calendar incorporates the user's locale and
// time zone settings, which means it's the one you'll use
// most often.
let userCalendar = Calendar.current


// March 10, 1876: The day Alexander Graham Bell
// made the first land line phone call
// ---------------------------------------------
// DateComponents' init method is very thorough, but very long,
// especially when we're providing only 3 pieces of information
let firstLandPhoneCallDateComponents = DateComponents(calendar: nil,
                                                      timeZone: nil,
                                                      era: nil,
                                                      year: 1876,
                                                      month: 3,
                                                      day: 10,
                                                      hour: nil,
                                                      minute: nil,
                                                      second: nil,
                                                      nanosecond: nil,
                                                      weekday: nil,
                                                      weekdayOrdinal: nil,
                                                      quarter: nil,
                                                      weekOfMonth: nil,
                                                      weekOfYear: nil,
                                                      yearForWeekOfYear: nil)

// With a calendar and a year, month, and day defined in
// a DateComponents struct, we can build a date
let firstLandPhoneCallDate = userCalendar.date(from: firstLandPhoneCallDateComponents)!
firstLandPhoneCallDate.timeIntervalSinceReferenceDate

In the code, we:

  • Get the user’s current Calendar.
  • Create an DateComponents struct, firstLandPhoneCallDateComponents, providing values for the year, month, and day parameters, and nil for all the others.
  • Use the user’s Calendar to create firstLandPhoneCallDate using firstLandPhoneCallDateComponents.
  • Get the internal representation of the Date.

Here’s a screenshot of the playground code as seen on my computer, whose time zone is set to “US/Eastern” (UTC-5):

firstlandphonecalldate

Click the screenshot to see it at full size.

Note the results in the sidebar at the lower right-hand corner:

  • firstLandPhoneCallDate‘s value corresponds to the DateComponents properties we set: March 10, 1876, 12:00 a.m..
  • firstLandPhoneCallDate‘s internal value, contained within its timeIntervalSinceReferenceDate property, is -3,938,697,748, which indicates that Alexander Graham Bell’s inaugural phone call was made nearly 4 billion seconds prior to the start of the Third Millennium.

Let’s create a Date given a year, month, and day, part 2

martin cooper

Let’s try creating another momentous date in phone history: the day when Martin Cooper made the first cellular phone call, April 3, 1973. We’ll do it differently this time, by creating a blank DateComponents struct, and then setting its year, month, and day properties. Add the following code to the code above:

// (Previous code goes here)

// April 3, 1973: The day Martin Cooper
// made the first cellular phone call
// ------------------------------------
// This time, we'll create a blank DateComponents struct
// and set its year, month, and day properties.
var firstCellPhoneCallDateComponents = DateComponents()
firstCellPhoneCallDateComponents.year = 1973
firstCellPhoneCallDateComponents.month = 4
firstCellPhoneCallDateComponents.day = 3

let firstCellPhoneCallDate = userCalendar.date(from: firstCellPhoneCallDateComponents)!
firstCellPhoneCallDate.timeIntervalSinceReferenceDate

In the code, we:

  • Create an empty DateComponents struct, firstCellPhoneCallDateComponents.
  • Set the year, month, and day properties of firstCellPhoneCallDateComponents to correspond to the date April 3, 1973.
  • Use the user’s Calendar to create firstCellPhoneCallDate using firstCellPhoneCallDateComponents.
  • Get the internal representation of the Date.

Here’s a screenshot of the results:

firstcellphonecalldate

Click the screenshot to see it at full size.

Let’s create a Date: What date does National Donut Day — the first Friday in June — fall on in 2017?

Having come from Canada, the country with the world’s highest per capita donut shop concentration and the people who eat the most donuts per capita, I can assure you that National Donut Day has been a real thing since 1938. It takes place on the first Friday in June, and we can find out what date it falls on in 2017 — or any other year — through the judicious use of DateComponents properties.

Add the following code to the current playground:

// (Previous code goes here)

// The first Friday in June, 2017:
// National Donut Day
// -------------------------------
var donutDayComponents = DateComponents()
donutDayComponents.year = 2017
donutDayComponents.month = 6
// We're looking for a Friday...
donutDayComponents.weekday = 6
// ...and it needs to be the first Friday of the month
donutDayComponents.weekdayOrdinal = 1

let donutDayDate = userCalendar.date(from: donutDayComponents)!

You should be familiar with the year and month DayComponents properties by now, and we’re using a couple that may be new to you:

  • weekday: Specifies a day of the week. With the Gregorian calendar, valid values are 1 through 7, where 1 is Sunday, 2 is Monday, 3 is Tuesday, and so on. Since we’re looking for a Friday, we’ve set this value to 6.
  • weekdayOrdinal: Specifies the order of the given weekday in the next larger specified calendar unit. Since we set weekday to 6 and set this value to 1, and since the next largest specified calendar unit was month, we’ll get the date of the first Friday of the month.

If you check the value of donutDayDate in the playground’s sidebar, you should see Jun 2, 2017, 12:00 AM. If you look at a calendar, you’ll confirm that it is indeed the first Friday of June 2017.

changing stuff and seing what happens

In the spirit of the fake book cover shown above, let’s see what happens if we don’t specify the month. Comment out the following line from the code you just added…

donutDayComponents.month = 6

…so that the code now looks like this:

// The first Friday in June, 2017:
// National Donut Day
// -------------------------------
var donutDayComponents = DateComponents()
donutDayComponents.year = 2017
//donutDayComponents.month = 6
// We're looking for a Friday...
donutDayComponents.weekday = 6
// ...and it needs to be the first Friday of the month
donutDayComponents.weekdayOrdinal = 1

let donutDayDate = userCalendar.date(from: donutDayComponents)!

When you run the code, you’ll see that the date for donutDayDate is now Jan 6 2017, 12:00 AM. Now that we’re specifying only a year and not a month, Swift interprets the combination of donutDayComponents.weekday = 6 and donutDayComponents.weekdayOrdinal = 1 to mean “the first Friday of the year”. If you look at a calendar, you’ll confirm that January 6, 2017 is indeed the first Friday of the year.

Let’s create one more Date: 5:00.pm. on Thursday of the 18th week of 2017…in Tokyo.

The great thing about Swift’s Calendar class is that it does its best to work with the DateComponents that you give it, and DateComponents gives you all sorts of ways to specify a date. Let’s assume for a moment that you’re in Japan and want to leave work at the ridiculously early hour of 5 p.m. and have some relaxing Suntory times, and it just happens to be the 18th week of 2017. What’s the date?

The answer comes from this code:

// (Previous code goes here)

// Thursday on the 18th week of 2017 in Tokyo
// ------------------------------------------
var thursday5pm18thWeek2017TokyoDateComponents = DateComponents()
thursday5pm18thWeek2017TokyoDateComponents.year = 2017
thursday5pm18thWeek2017TokyoDateComponents.weekOfYear = 18
thursday5pm18thWeek2017TokyoDateComponents.weekday = 5
thursday5pm18thWeek2017TokyoDateComponents.hour = 17
thursday5pm18thWeek2017TokyoDateComponents.timeZone = TimeZone(identifier: "Asia/Tokyo")!

let thursday5pm18thWeek2017TokyoDate = userCalendar.date(from: thursday5pm18thWeek2017TokyoDateComponents)!

On my system, which is in the Eastern daylight time zone (UTC-4) at the time of writing, thursday5pm18thWeek2017TokyoDate displays as May 4, 2017, 4:00 AM in my playground’s sidebar, and looking at a calendar confirms that May 4th is indeed the Thursday of the 18th month of 2017.

Let’s extract DateComponents from a Date, part 1

Now that we’ve created some Dates using DateComponents, let’s do the reverse and extract DateComponents from given Dates. We’ll continue with our playground and use a Date we’ve already created: firstLandPhoneCallDate, which corresponds to the date of Alexander Graham Bell’s historic phone call, March 10, 1876. Here’s code that extracts the year, month, and day from this Date:

// (Previous code goes here)

// We want to extract the year, month, and day from firstLandPhoneCallDate
let alexanderGrahamBellDateComponents = userCalendar.dateComponents([.year, .month, .day],
                                                                    from: firstLandPhoneCallDate)
alexanderGrahamBellDateComponents.year     // 1876
alexanderGrahamBellDateComponents.month    // 3
alexanderGrahamBellDateComponents.day      // 10

Let’s extract DateComponents from a Date, part 2

This time, let’s create a new Date — one that corresponds to this key date in iOS history: the “Stevenote” where the original iPhone was first announced:

If you were to ask Swift when this Stevenote took place, it would reply “190,058,400 seconds after the reference date”. For most of us, this is a meaningless figure, so we’ll extract the following DateComponents from this Date:

  • Year
  • Month
  • Day
  • Hour
  • Minute
  • What day of the week this Date fell on
  • What week of the year this Date fell on

Here’s the code:

// (Previous code goes here)

// The "Stevenote" where the iPhone was announced took place
// 190,058,400 seconds after the start of the Third Millennium.
let iPhoneStevenoteDate = Date(timeIntervalSinceReferenceDate: 190_058_400)

// We want to extract the year, month, day, hour, and minute from this date,
// and we also want to know what day of the week and week of the year
// this date fell on.
let iPhoneStevenoteDateComponents = userCalendar.dateComponents(
      [.year, .month, .day, .hour, .minute, .weekday, .weekOfYear],
      from: iPhoneStevenoteDate)
iPhoneStevenoteDateComponents.year!        // 2007
iPhoneStevenoteDateComponents.month!       // 1
iPhoneStevenoteDateComponents.day!         // 9
iPhoneStevenoteDateComponents.hour!        // 13
iPhoneStevenoteDateComponents.minute!      // 0
iPhoneStevenoteDateComponents.weekday!     // 3 (Tuesday)
iPhoneStevenoteDateComponents.weekOfYear!  // 2 (2nd week of the year)

Let’s extract DateComponents from a Date, part 3

Let’s try it again with another key iOS date — the Stevenote where the original iPad was announced:

This time, if you were to ask Swift when this Stevenote took place, it would reply “286,308,000 seconds after the reference date”. Let’s get all the DateComponents for this date:

// (Previous code goes here)

// The "Stevenote" where the original iPad was announced took place
// 286,308,00 seconds after the start of the Third Millennium.
let iPadSteveNoteDate = Date(timeIntervalSinceReferenceDate: 286_308_000)

// We want to extract ALL the DateComponents.
let iPadSteveNoteDateComponents = userCalendar.dateComponents([.calendar,
                                                               .day,
                                                               .era,
                                                               .hour,
                                                               .minute,
                                                               .month,
                                                               .nanosecond,
                                                               .quarter,
                                                               .second,
                                                               .timeZone,
                                                               .weekday,
                                                               .weekdayOrdinal,
                                                               .weekOfMonth,
                                                               .weekOfYear,
                                                               .year,
                                                               .yearForWeekOfYear],
                                                              from: iPadSteveNoteDate)
iPadSteveNoteDateComponents.calendar?.identifier // gregorian
iPadSteveNoteDateComponents.day!                 // 27
iPadSteveNoteDateComponents.era!                 // 1
iPadSteveNoteDateComponents.hour!                // 13
iPadSteveNoteDateComponents.minute!              // 0
iPadSteveNoteDateComponents.month!               // 1
iPadSteveNoteDateComponents.nanosecond!          // 0
iPadSteveNoteDateComponents.quarter!             // 0
iPadSteveNoteDateComponents.second!              // 0
iPadSteveNoteDateComponents.timeZone!            // Eastern time zone
iPadSteveNoteDateComponents.weekday!             // 4 (Wednesday)
iPadSteveNoteDateComponents.weekdayOrdinal!      // 4 (4th Wednesday in the month)
iPadSteveNoteDateComponents.weekOfMonth!         // 5 (5th week of the month)
iPadSteveNoteDateComponents.weekOfYear!          // 5 (5th week of the year)
iPadSteveNoteDateComponents.year!                // 2010
iPadSteveNoteDateComponents.yearForWeekOfYear!   // 2010

Let’s take a look at each DateComponents property and what it represents:

Property Description
calendar The calendar system for the date represented by this set of DateComponents. We got these DateComponents by converting a Date using a Gregorian Calendar, so in this case, this value is gregorian.
day The day number of this particular date and time. For January 27, 2010, 18:00:00 UTC, this value is 27.
era The era for this particular date, which depends on the date’s calendar system. In this case, we’re using the Gregorian calendar, which has two eras:

  • BCE (a.k.a. BC), represented by the integer value 0
  • CE (a.k.a. AD), represented by the integer value 1
hour The hour number of this particular date and time. For January 27, 2010, 18:00:00 UTC, this value is 13, because in my time zone, 18:00:00 UTC is 13:00:00.
minute The minute number of this particular date and time. For January 27, 2010, 18:00:00 UTC, this value is 0.
month The month number of this particular date and time. For January 27, 2010, 18:00:00 UTC, this value is 1.
nanosecond The nanosecond number of this particular date and time. For January 27, 2010, 18:00:00 UTC, this value is 0.
quarter The quarter number of this particular date and time. January 27, 2010, 18:00:00 UTC, is in the first quarter of the year, so this value is 0.
second The second number of this particular date and time. For January 27, 2010, 18:00:00 UTC, this value is 0.
timeZone The time zone of this particular date and time. I’m in the UTC-5 time zone (US Eastern), so this value is set to that time zone.
weekday The day of the week of this particular date and time. In the Gregorian calendar, Sunday is 1, Monday is 2, Tuesday is 3, and so on. January 27, 2010, was a Wednesday, so this value is 4.
weekdayOrdinal The position of the weekday within the next larger specified calendar unit, which in this case is a month. So this specifies nth weekday of the given month. Jauary 27, 2010 was on the 4th Wednesday of the month, so this value is 4.
weekOfMonth The week of the month of this particular date and time. January 27, 2010 fell on the 5th week of January 2010, so this value is 5.
weekOfYear The week of the year of this particular date and time. January 27, 2010 fell on the 5th week of 2010, so this value is 5.
year The year number of this particular date and time. For January 27, 2010, 18:00:00 UTC, this value is 2010.
yearForWeekOfYear Oh wow, this is so hard to explain that I’ll leave it to Apple’s docs.

Wrapping it all up

Here’s the playground containing all the code we just worked with:

// The user's calendar incorporates the user's locale and
// time zone settings, which means it's the one you'll use
// most often.
let userCalendar = Calendar.current


// March 10, 1876: The day Alexander Graham Bell
// made the first land line phone call
// ---------------------------------------------
// DateComponents' init method is very thorough, but very long,
// especially when we're providing only 3 pieces of information
let firstLandPhoneCallDateComponents = DateComponents(calendar: nil,
                                                      timeZone: nil,
                                                      era: nil,
                                                      year: 1876,
                                                      month: 3,
                                                      day: 10,
                                                      hour: nil,
                                                      minute: nil,
                                                      second: nil,
                                                      nanosecond: nil,
                                                      weekday: nil,
                                                      weekdayOrdinal: nil,
                                                      quarter: nil,
                                                      weekOfMonth: nil,
                                                      weekOfYear: nil,
                                                      yearForWeekOfYear: nil)

// With a calendar and a year, month, and day defined in
// a DateComponents struct, we can build a date
let firstLandPhoneCallDate = userCalendar.date(from: firstLandPhoneCallDateComponents)!
firstLandPhoneCallDate.timeIntervalSinceReferenceDate


// April 3, 1973: The day Martin Cooper
// made the first cellular phone call
// ------------------------------------
// This time, we'll create a blank DateComponents struct
// and set its year, month, and day properties.
var firstCellPhoneCallDateComponents = DateComponents()
firstCellPhoneCallDateComponents.year = 1973
firstCellPhoneCallDateComponents.month = 4
firstCellPhoneCallDateComponents.day = 3

let firstCellPhoneCallDate = userCalendar.date(from: firstCellPhoneCallDateComponents)!
firstCellPhoneCallDate.timeIntervalSinceReferenceDate


// The first Friday in June, 2017:
// National Donut Day
// -------------------------------
var donutDayComponents = DateComponents()
donutDayComponents.year = 2017
donutDayComponents.month = 6
// We're looking for a Friday...
donutDayComponents.weekday = 6
// ...and it needs to be the first Friday of the month
donutDayComponents.weekdayOrdinal = 1

let donutDayDate = userCalendar.date(from: donutDayComponents)!


// Thursday on the 18th week of 2017 in Tokyo
// ------------------------------------------
var thursday5pm18thWeek2017TokyoDateComponents = DateComponents()
thursday5pm18thWeek2017TokyoDateComponents.year = 2017
thursday5pm18thWeek2017TokyoDateComponents.weekOfYear = 18
thursday5pm18thWeek2017TokyoDateComponents.weekday = 5
thursday5pm18thWeek2017TokyoDateComponents.hour = 17
thursday5pm18thWeek2017TokyoDateComponents.timeZone = TimeZone(identifier: "Asia/Tokyo")!

let thursday5pm18thWeek2017TokyoDate = userCalendar.date(from: thursday5pm18thWeek2017TokyoDateComponents)!


var tokyoCalendar = Calendar(identifier: .ethiopicAmeteAlem)
tokyoCalendar.timeZone = TimeZone(identifier: "Asia/Tokyo")!


firstLandPhoneCallDate.timeIntervalSinceReferenceDate

// We want to extract the year, month, and day from firstLandPhoneCallDate
let alexanderGrahamBellDateComponents = userCalendar.dateComponents([.year, .month, .day],
                                                                    from: firstLandPhoneCallDate)
alexanderGrahamBellDateComponents.year     // 1876
alexanderGrahamBellDateComponents.month    // 3
alexanderGrahamBellDateComponents.day      // 10


// The "Stevenote" where the original iPhone was announced took place
// 190,058,400 seconds after the start of the Third Millennium.
let iPhoneStevenoteDate = Date(timeIntervalSinceReferenceDate: 190_058_400)

// We want to extract the year, month, day, hour, and minute from this date,
// and we also want to know what day of the week and week of the year
// this date fell on.
let iPhoneStevenoteDateComponents = userCalendar.dateComponents(
      [.year, .month, .day, .hour, .minute, .weekday, .weekOfYear],
      from: iPhoneStevenoteDate)
iPhoneStevenoteDateComponents.year!        // 2007
iPhoneStevenoteDateComponents.month!       // 1
iPhoneStevenoteDateComponents.day!         // 9
iPhoneStevenoteDateComponents.hour!        // 13
iPhoneStevenoteDateComponents.minute!      // 0
iPhoneStevenoteDateComponents.weekday!     // 3 (Tuesday)
iPhoneStevenoteDateComponents.weekOfYear!  // 2 (2nd week of the year)


// The "Stevenote" where the original iPad was announced took place
// 286,308,00 seconds after the start of the Third Millennium.
let iPadSteveNoteDate = Date(timeIntervalSinceReferenceDate: 286_308_000)

// We want to extract ALL the DateComponents.
let iPadSteveNoteDateComponents = userCalendar.dateComponents([.calendar,
                                                               .day,
                                                               .era,
                                                               .hour,
                                                               .minute,
                                                               .month,
                                                               .nanosecond,
                                                               .quarter,
                                                               .second,
                                                               .timeZone,
                                                               .weekday,
                                                               .weekdayOrdinal,
                                                               .weekOfMonth,
                                                               .weekOfYear,
                                                               .year,
                                                               .yearForWeekOfYear],
                                                              from: iPadSteveNoteDate)
iPadSteveNoteDateComponents.calendar?.identifier // gregorian
iPadSteveNoteDateComponents.day!                 // 27
iPadSteveNoteDateComponents.era!                 // 1
iPadSteveNoteDateComponents.hour!                // 13
iPadSteveNoteDateComponents.minute!              // 0
iPadSteveNoteDateComponents.month!               // 1
iPadSteveNoteDateComponents.nanosecond!          // 0
iPadSteveNoteDateComponents.quarter!             // 0
iPadSteveNoteDateComponents.second!              // 0
iPadSteveNoteDateComponents.timeZone!            // Eastern time zone
iPadSteveNoteDateComponents.weekday!             // 4 (Wednesday)
iPadSteveNoteDateComponents.weekdayOrdinal!      // 4 (4th Wednesday in the month)
iPadSteveNoteDateComponents.weekOfMonth!         // 5 (5th week of the month)
iPadSteveNoteDateComponents.weekOfYear!          // 5 (5th week of the year)
iPadSteveNoteDateComponents.year!                // 2010
iPadSteveNoteDateComponents.yearForWeekOfYear!   // 2010

In the next installment, we’ll look at converting Dates to Strings, and vice versa.

Categories
Uncategorized

The truth about typefaces

IMG_2593

This one goes out to all the front-end and interface designers and developers out there.

Categories
Hardware What I’m Up To

Unboxing the CanaKit Raspberry Pi 3 Complete Starter Kit

raspberry pi 12
Click the photo to see it at full size.

On the most recent Amazon Prime Day — an annual trick that Amazon pulls in order to boost sales in the same vein as Cyber Monday, but in the summer — I managed to limit myself to buying just one sale-priced thing that I didn’t really need: the CanaKit Raspberry Pi 3 Complete Starter Kit. It normally sells on Amazon for US$75, but it was on sale that day for US$60.

The Raspberry Pi 3 is the current version of a series of single-board computers about the size of a deck of playing cards, and are:

I plan to use the Raspberry Pi to make some initial delving into IoT (Internet of Things) development, and as part of my journey into developing for that category of computer that I call “tiny and shiny” — smartphones, tablets, and now Raspberry Pi / Arduino-type boards.

Here’s the CanaKit Raspberry Pi 3 Complete Start Kit box:

raspberry pi 01

When I opened it, I saw this:

raspberry pi 02

The first thing you should see is a greeting card that also provides an email address for assistance, should you need it. The other side of the card has a diagram explain what each of the GPIO interface pins on the Raspberry Pi 3 board is for.

Below the card was an HDMI cable:

raspberry pi 03

And below that were three boxes:

raspberry pi 04

From largest to smallest, the three boxes contained the Raspberry Pi 3 board and SD card (which functions as its “hard drive”)…

raspberry pi 05

…a case for the board…

raspberry pi 06

…and a power supply for the board:

raspberry pi 07

Below the boxes were these items:

raspberry pi 08

One bag contained a USB microSD card reader. It allows you to use your regular computer to download updated or different versions of the Raspberry Pi OS or software and transfer them onto the microSD card:

raspberry pi 09

The other bag contained two heatsinks for its chips. They already have heatsink adhesive attacked to them; you just have to peel off the backing and stick them onto their respective chips:

raspberry pi 10

At the bottom of the box was the “quick start” guide:

raspberry pi 11

Here’s the board mounted in the lower tray portion of the case:

raspberry pi 13

And here’s the board with the middle section of the case attached:

raspberry pi 14

And here’s what the Pi looks like once the case is assembled:

raspberry pi 15

Assembling the case is pretty easy, as no tools are required. It simply snaps together.

Here’s the case on my desk, placed beside a $20 bill for size comparison:

raspberry pi 16

The Pi case is smaller than the hard drive that I connected to it (you can see it below the Pi):

raspberry pi 18

I decided to take the beginner route and start up the system using NOOBS, short for “New out of the box software”. It came pre-loaded onto the SD card that came with the board, and it installed Raspbian, the official supportedRaspberry Pi OS, and based on Debian. Once the OS is installed, here’s what you see when you boot up the Pi:

raspberry pi 19

Once it finishes booting up, you’re taken to a GNOME desktop:

raspberry pi 20

I used to have a stack of USB keyboards, but I’d given most of them away to friends and family, and my last couple are still back in Toronto. Figuring that I’d end up taking the Pi to meetups, BarCamps, and other demo sessions, or perhaps use it as a living room media center / internet device, I went with the Logitech K400 all-in-one keyboard, shown below. It’s currently on sale at Walmart for US$20:

raspberry pi 21

And thanks to Anastasia Sistevaris, an intern at Wiley, I got hooked up with a set of Raspberry Pi books, the first of which arrived recently: Exploring Raspberry Pi by Derek Molloy. I’ll do a writeup of this book in a later article:

raspberry pi 22

Watch this space for more Raspberry Pi articles as I start noodling with my new toy!

Categories
Uncategorized

Ron Klein – the inventor of credit card validation via magnetic strip – speaks at Next Money TPA

ron and arlene klein at next money tpa

Click the photo to see it at full size.

Last night, I had the pleasure of meeting inventor Ron Klein and his wife Arlene, at the Next Money TPA meetup. If you’re a reader of this blog, it’s likely that you’ve used at least one of his innovations:

  • The MLS — as in multiple listing service — for real estate,
  • Interactive voice response for banks,
  • a bond monitoring system for Wall Street traders…

…and then there’s the innovation you’ve most likely used — automated validation of credit cards through the use of a magnetic stripe:

He was also an artillery forward observer in the Korean War, where he went on 58 missions. He got hurt during the last one, resulting in a spinal injury, and earning him a Purple Heart. The injury caused him painful spinal stenosis, where the bones in his spine put pressure the spinal cord and related nerves leading from it. He took up exercise, which he found was pain-relieving, and does it so often that he’s participated and won medals in the Florida Senior Games.

ron klein with bike

In the bad old days, credit card validation was done manually. Any merchant that accepted payments via credit card was given a long paper list of “bad” credit card numbers, and would have to “eyeball” the list in order to valid a credit card. I remember when this sort of thing was still done in the early 1970s, and it was slow even under the best of circumstances, never mind during big sales or something like Black Friday.

Klein, then director of engineering for Ultronics Systems Corporation — which would later become part of GT&E Financial — developed a “validity-checking system”, which allowed merchants to enter credit card numbers into a “desk-mountable interrogation unit” that could check against a central store of credit card numbers which would be stored in drum memory. If the account number on the card wasn’t on the “bad” list, the desk unit would show a “credit good” light; otherwise, it would display an error signal.

According to CreditCards.com, Klein’s original design for the verifier was such that a bad credit card would be held by the device. “If the credit wasn’t good,” he said, “it locked up the card so that the person didn’t get the card back, because the merchant got credit for capturing negative-account cards.”

At the age of 81, Ron could simply enjoy a quiet retirement, but that’s not his style. “I took three months off, but I got bored,” he said. “I’d rather keep busy, taking on new challenges. I’m not empty yet!”

He spoke to the group for about 90 minutes, regaling us with stories about his childhood, the business world, and his drive to find solutions to problems.

One theme he kept repeating to the meetup group was to simplify. “There’s a fix for everything, a solution for every challenge. The trick is to simplify. Identify the problem, simplify, then be smart, daring, and different.”

Another bit of advice he gave to the group was to “Be a smiling cobra, and never point an unloaded gun,” which I took to mean be nice as much as you can, but be tough when you have to — and mean it. I found him to be quite affable, but if he managed to operate in the world of Wall Street, I can he his need to be a cobra from time to time.

ron and arlene 2

His last bit of advice to the group was to “sell the benefit, not the idea”. This is a good reminded for anyone who’s inventing a product or service — nobody cares about inventions for their own sake, but the benefits they provide. This may seem obvious to some, but as I like to say, there’s great power in stating the obvious.

Ron lives in Sarasota, about an hour and a quarter south of my place. I may have to drive down there sometime, take him and Arlene out to lunch, just so I can hear more stories about the things he created — and is still creating. My thanks to Ron and Arlene for appearing at the Next Money TPA meetup!

next money tpa

Next Money TPA is the Tampa chapter of Next Money, an international group of fintech communities, and the meetup group that brought Ron Klein to speak. Next Money TPA brings together people from the Tampa Bay area to discuss the intersection of finance, technology, design, and creative spaces. Organized by Bruce Burke, the meetup invites “casual, entrepreneurial, inquisitive minds” to gather, share ideas, and meet each other.

Categories
Uncategorized

Learn Core Location at the Suncoast iOS Meetup this Thursday, July 28th!

location services

If you’re an iOS developer in the Tampa Bay area and looking for something to do this Thursday evening, you’ll want to check out the Suncoast iOS Meetup. This session is called Core Location In depth: Get your location even if your app gets killed!

Here’s the abstract for the meetup:

In this session, I will explain in depth how the iPhone gets your location and which APIs are available in the latest version of iOS.

  • Do you know that the iPhone combines three different radio signals to obtain your location?
  • Do you know how to track the location even when your app is not running?
  • Do you want to get an alert when the user arrives to one specific location?
  • Even if your app is killed or is not active?
  • Do you know how to debug your location code with the iOS simulator?

Come to the session and you’ll get the answers.

This session will be a presentation with some slides and some short demos with Xcode. No prior knowledge is necessary. Everyone is welcomed.

juan catalanSuncoast iOS Meetup is organized by Craig Clayton and Juan Catalan, both of whom write apps for a living. I’m going to catch this one, partly because it’s been too long since I last attended a Suncoast iOS Meetup, partly because I’ve never seen Juan present, and partly because I can’t answer “yes” with complete certainty to all the questions in the abstract.

This meetup will take place this Thursday, July 28th at 7:00 p.m. at Tampa Bay Wave, located in downtown Tampa (500 East Kennedy Boulevard, 3rd floor). Attendance is free, but you should register to attend!

Categories
Uncategorized

The Pokémon Go developer roundup for July 23, 2016

Pokémon Go is the number one app for iOS and Android

[via Polygon] On Friday, Apple confirmed that Pokémon Go got more downloads in its first week than any other app in the history of the App Store, which opened just over eight years ago on July 10, 2008. Apple won’t get any more specific than that, Nintendo are referring all inquiries about download statistics to The Pokémon Company, and nobody’s heard anything from them. The “mium” part of “freemium” means that Pokémon Go still makes money — anywhere from $1 million daily (according to Business Insider, or whomever they’ve semi-plagiarized) to $2.3 million daily (according to Superdata Research).

top free apps

At the time of writing, Pokémon Go holds the number one position on the “Free” and “Top Grossing” charts of both the App Store and Google Play. Nicolas Beraudo, the EMEA managing director for the mobile analytics firm App Annie says that “I can easily envision a run-rate of over $1 billion per year with less server issues, a worldwide presence, and more social and [player vs. player] features.”

A Pokémon Go utility is the number 3 free app on the App Store

poke radar tampa

As I write this, the number 3 free app on the App Store is a third-party Pokémon Go utility app called Poké Radar. It’s a crowdsourced Pokémon location database that lets players find or submit Pokémon encounter locations worldwide. The image above is a screenshot from Poké Radar that shows user-submitted Pokémon encounters in my stomping grounds, the Tampa Bay area.

This likely won’t be the last third-party Pokémon Go utility; the current Pokémon craze and potential $1 billion pie means that even a small slice of the business is too big an opportunity to pass up. If you’ve got the time and the resources, you should try developing a Pokémon Go helper app.

Where to go if you’re thinking about writing a Pokémon Go app

pokemongodev

Not surprisingly, a number of online resources for developers interested in building Pokémon Go tools have appeared online. This is a hot new topic, and you should expect to see new resources spring up quite often for the next few weeks, but here are the three best starting points that I’m aware of:

A word of warning: Some of the code pointed to by these resources appears to use not-necessarily-approved access to data streams between devices and Pokémon Go servers. All the standard “I am not a lawyer” and “Caveat implementor” warnings apply.

Categories
Current Events Florida Tampa Bay

A walk through my “Just enough React to get you into trouble” presentation at Tampa Code Camp 2016

just enough react title slide

I had the opening presentation in the “Miscellaneous and Open Source” track of Tampa Code Camp 2016, which took place on July 16th. My presentation was titled Just enough React to get you into trouble, and was designed to be an introduction to building user interfaces using React.

In 50 minutes, I introduced React to the audience mostly by live-coding a simple React application in a JSFiddle playground. For those of you who missed it (or saw it and wanted to review it), this article walks you through my presentation. Enjoy!

Playing around with React in a JSFiddle playground

I spent most of my presentation live-coding some a simple React application in JSFiddle, a “playground” that lets you quickly try out web development ideas in your browser and save them for later use. A saved “playground” is called a fiddle, and you can fork other people’s public fiddles for your own experimentation.

JSFiddle has four key areas — HTML, CSS, JavaScript, and output, as shown below:

jsfiddle diagram

Click the screenshot to see it at full size.

JSFiddle lets you enter the HTML, CSS, and JavaScript into the corresponding areas and then see the result in the output area by clicking on the Run button located near the upper left-hand corner of the page. It even lets you import a number of JavaScript and CSS libraries.

In this exercise, we’ll work using a base fiddle that imports the libraries necessary for a React application, and we’ll do all of our coding in the JavaScript area.

Let’s start with a simple React fiddle

Let’s start by navigating to the fiddle that I set up as the starting point for the presentation. I forked it from the React base fiddle, and if you set up your own JSFiddle account, you should fork it for yourself.

The fiddle features one of the simplest React applications that you can write: “Hello, world” for React. Here’s the JavaScript:

class Hello extends React.Component {

  render() {
    return <h1>Hello, world!</h1>
  }

}


ReactDOM.render(
  <Hello />,
  document.getElementById('app')
)

And here’s a screenshot showing the output:

hello world

Let’s take a closer look at what’s going on in the JavaScript code…

1. First, we create a React component named Hello.

React is all about creating user interfaces by assembling modular, composable components. For this first example, we want to create a component named Hello, which is made up of a single <h1> heading. We do this by creating a class named Hello, which subclasses React’s React.Component class:

class Hello extends React.Component {

  render() {
    return <h1>Hello, world!</h1>
  }

}

Our Hello class has a single method, render. React component classes can implement many methods, but must implement a method called render, which returns a value that shows how the component should be drawn onscreen. The value returned by render depends on the kind of React app we’re working on:

  • In a web application, the render method returns a single HTML element. This single HTML element is allowed to contain other HTML elements.
  • In a native mobile application, the render method returns a single view. This single view is represented in a dialect of XML whose elements represent native mobile UI elements. This view is allowed to contain other views.

(For now, we’ll stick to React web applications. I’ll look at React native applications in a later article.)

Here’s the value returned by the render method:

<h1>Hello, world!</h1>

You’ve probably noticed that it’s not in quotes as you might have expected. That’s because render‘s return value isn’t a string that contains HTML.

Instead, its return value is JSX, a dialect of XML whose name is short for “JavaScript XML”. It looks like HTML, and it’s meant to — it’s a shorthand for the value that the render method actually returns, which is a React element — a JavaScript object. This fiddle — and many React applications — includes a extension that preprocesses JSX into JavaScript that generates a React element.

Here’s what render really returns, once the JSX has been processed into JavaScript:

React.createElement("h1", null, "Hello, world!")

In fact, you can have render directly return a React element. Try changing the render method so that it looks like this, then click the Run button to run the app:

render() {
  return React.createElement("h1", null, "Hello, world -- the hard way!")
}

The output should look like this:

hello world the hard way

Click the screenshot to see it at full size.

Generally, React developers prefer to work with JSX. It’s preprocessed, so using it doesn’t affect your application’s efficiency, and it’s much easier to read, especially as you work on more complex React projects.

2. Then we render the Hello component onto the page.

Here’s the line that renders the Hello component onto the page:

ReactDOM.render(
  <Hello />,
  document.getElementById('app')
)

The ReactDOM.render method takes two arguments:

  1. A React element to render. In this case, the react element is the output of Hello‘s render method, which we request by using the JSX tag <Hello />.
  2. The DOM node where the React element will be rendered. In this case, we specify that it should be rendered in the node whose id is app. If you look in the HTML area of the fiddle, you’ll see it at the very end:
<div id="app">
    <!-- 
    This element's contents will be filled by our React code's output.
    -->
</div>

This is one of the two things you should take away from this tutorial: At its core, building user interfaces in React is about defining components and then rendering them onto the screen. Everything else builds on this basic principle.

Let’s continue. If you changed the render method in Hello to use JavaScript instead of JSX, change it back. The code in the JavaScript area of the page should look like this:

class Hello extends React.Component {

  render() {
    return <h1>Hello, world!</h1>
  }

}


ReactDOM.render(
  <Hello />,
  document.getElementById('app')
)

Pass information to a component with a prop

Suppose we want our application to be a little more flexible in who it says “Hello” to. Let’s change the component so that it can be passed a name parameter, and then says “Hello,” followed by that name.

Update the code in the JavaScript area so that it looks like this:

class Hello extends React.Component {

  render() {
    const name = this.props.name
    return <h1>Hello, {name}!</h1>
  }

}


ReactDOM.render(
  <Hello name="Kate" />,
  document.getElementById('app')
)

Let’s first look at the ReactDOM.render line. Note that we’ve added an attribute to the Hello element:

<Hello name="Kate" />

The use of XML attributes in React elements allows us to pass values to the corresponding components. In the Hello element, we’re using an attribute called name to pass the string “Kate” to our Hello component.

Within the Hello component’s render method, we access that value by using the component’s props (short for properties) object and assign its value to a variable…

const name = this.props.name

…and then we use that variable within the JSX returned by the render method. Note that the variable is delimited by { }:

return <h1>Hello, {name}!</h1>

When you click on the Run button in JSFiddle, here’s what you should see:

hello kate 1

Click the screenshot to see it at full size.

For components, props are read-only — they can take in props and use their values, but they can’t change them. They’re meant to be used to set up components.

Using multiple props and rendering more stuff

Let’s change our app so that it says “Hello, Kate!” followed by a greeting:

class Hello extends React.Component {

  render() {
    const name = this.props.name
    const greeting = this.props.greeting
    return <h1>Hello, {name}!</h1>
           <p>{greeting}, {name}.</p>
  }

}


ReactDOM.render(
  <Hello name="Kate" greeting="Welcome to Tampa Code Camp" />,
  document.getElementById('app')
)

If you click the Run button right now, the output area will contain…nothing:

hello kate 1

Click the screenshot to see it at full size.

In many cases, when the output area is blank when you don’t expect it to be, it means that there’s an error in your code. In this case, it’s the fact that the render method is supposed to return only one HTML element, but our returns two:

<h1>Hello, {name}!</h1>
<p>{greeting}, {name}.</p>

While render is supposed to return a single HTML element, that single element is allowed to contain other elements. The fix is to take our two elements and enclose them in a <div> like so:

<div>
  <h1>Hello, {name}!</h1>
  <p>{greeting}, {name}.</p>
</div>

Here’s what your code should look like now…

class Hello extends React.Component {

  render() {
    const name = this.props.name
    const greeting = this.props.greeting
    return (<div>
      <h1>Hello, {name}!</h1>
      <p>{greeting}, {name}.</p>
    </div>)
  }

}


ReactDOM.render(
  <Hello name="Kate" greeting="Welcome to Tampa Code Camp" />,
  document.getElementById('app')
)

…and here’s what things should look like when you hit the Run button:

hello kate 2

Click the screenshot to see it at full size.

Introducing default props

In addition to passing values to React components using props, we can also create default values through the use of default props. Change the code in the JavaScript area of the fiddle so that it looks like this:

class Hello extends React.Component {
  
  render() {
    const name = this.props.name
    const greeting = this.props.greeting
    return (<div>
      <h1>Hello, {name}!</h1>
      <p>{greeting}, {name}.</p>
    </div>)
  }

}

Hello.defaultProps = {
  name: "stranger",
  greeting: "Please press the button"
}


ReactDOM.render(
  <Hello />,
  document.getElementById('app')
)

Note that the <Hello> tag in the ReactDOM.render call doesn’t contain any attributes. This means that we’re not passing any props to it, which in turn means that our Hello component will use the default props defined in this line of code:

Hello.defaultProps = {
  name: "stranger",
  greeting: "Please press the button"
}

If you run the application, you’ll see that the Hello component uses the default props, addressing the user as “stranger” and using the greeting “Please press the button”:

hello stranger

Click the screenshot to see it at full size.

However, if we change the <Hello> tag in the ReactDOM.render call so that it has name and greeting attributes, as shown in the code below…

class Hello extends React.Component {
  
  render() {
    const name = this.props.name
    const greeting = this.props.greeting
    return (<div>
      <h1>Hello, {name}!</h1>
      <p>{greeting}, {name}.</p>
    </div>)
  }

}

Hello.defaultProps = {
  name: "stranger",
  greeting: "Please tell me your name"
}


ReactDOM.render(
  <Hello name="Kate" greeting="Welcome to Tampa Code Camp" />,
  document.getElementById('app')
)

…when you run the application, the Hello component uses the given props, addressing the user as “Kate” and using the greeting “Welcome to Tampa Code Camp”:

hello kate 3-2

Click the screenshot to see it at full size.

Adding state and interactivity

As I mentioned earlier, as far as components are concerned, props are read-only. They can only be set by attributes in the tags that invoke them and in the statement that sets their default values. With only read-only data like props, components themselves would also be read-only. What we need is data that components can change in response to user input or events, and that’s what state is for.

State is represented by the state object, which every React component has. Like the props object, it’s a “dictionary” that components can use to store values. However, there are two key differences between state and props:

  1. Unlike with the props object, the state object is read-write. Components can change the values within the state object by using the setState method.
  2. Any change to a component’s state object causes its render method to be called.

That second difference is key; in fact, it’s why the library is called “React”. The name is a nod to reactive programming, which is often defined as being “oriented around data flows and the propagation of change” (in fact, Wikipedia uses his definition). A greatly simplified way to describe it as “programming code that responds to changes in data”.

And now, here’s the second of the two things you should take away from this tutorial: Making changes to React components is all about changing their state. Or, if you’re into snappy rhyming mantras or hip-hop, remember it this way: Change the state to make it update.

Modify the code in the JavaScript area so that it looks like this. Don’t worry about any of the unfamiliar stuff; I’ll walk you through it in a moment:

class Hello extends React.Component {

  constructor(props) {
    super(props)
    this.onSubmit = this.onSubmit.bind(this)
    this.state = {
      name: this.props.name,
      greeting: this.props.greeting
    }
  }
  
  render() {
    const name = this.state.name
    const greeting = this.state.greeting
    return (<div>
      <h1>Hello, {name}!</h1>
      <p>{greeting}, {name}.</p>
      
      <form onSubmit={this.onSubmit}>
        <button>Update!</button>
      </form>
    </div>)
  }
  
  onSubmit(event) {
    event.preventDefault()
    this.setState({
      name: "button-presser",
      greeting: "Thanks for pressing the button"
    })
  }

}

Hello.defaultProps = {
  name: "stranger",
  greeting: "Please press the button"
}


ReactDOM.render(
  <Hello />,
  document.getElementById('app')
)

When you press the Run button, you should be greeted with “Hello, stranger!”, an invitation to press a button, and a button, as shown below…

hello stranger 2

Click the screenshot to see it at full size.

…and when you press that button, the name you’re referred to and the message below it change:

hello stranger 3

Click the screenshot to see it at full size.

Let’s take a closer look at the code. We’ll start with the render method, which is often a good place to start analyzing React components:

render() {
  const name = this.state.name
  const greeting = this.state.greeting
  return (<div>
    <h1>Hello, {name}!</h1>
    <p>{greeting}, {name}.</p>
      
    <form onSubmit={this.onSubmit}>
      <button>Update!</button>
    </form>
  </div>)
}

The main difference between this render method and the previous one is the addition of this form code:

<form onSubmit={this.onSubmit}>
  <button>Update!</button>
</form>

The onSubmit attribute of the <form> tag is set to {this.onSubmit}, which means that when the form is submitted — which in turn that means that the user has clicked the button — the class’ onSubmit method is called. Let’s look at onSubmit now:

onSubmit(event) {
  event.preventDefault()
  this.setState({
    name: "button-presser",
    greeting: "Thanks for pressing the button"
  })
}

Two things are happening in this method:

  1. First, the event.preventDefault method is called. This stops the page from reloading, which is the default behavior when a form is submitted (it also explains the name of the method).
  2. Then, the setState method is called, which changes the properties of the state object so that:
    • name‘s value is changed to “button-presser”, and
    • greeting‘s value is changed to “Thanks for pressing the button”.

And since we’ve changed state, the render method gets called, which in turn causes it to display the new state values.

Finally, let’s take a look at the constructor:

constructor(props) {
  super(props)
  this.onSubmit = this.onSubmit.bind(this)
  this.state = {
    name: this.props.name,
    greeting: this.props.greeting
  }
}

Here’s what’s happening in this method:

  1. The props argument that constructor takes contains the properties that were passed to Hello via the <Hello> tag’s attributes. As with constructors in many other programming languages, we pass this argument to the component’s superclass with super(props).
  2. The onSubmit attribute of our form specifies that the this.onSubmit method should be called when the form is submitted. The problem is that within the JSX, the this in this.onSubmit is undefined. We solve this problem by binding the onSubmit method to this specific instance of the Hello class, so that the this in this.onSubmit points to this instance (if you’re skeptical, comment out the line this.onSubmit = this.onSubmit.bind(this) and try running the app). You’ll need to do this sort of binding for every method that you call from JSX.
  3. And finally, we update the state object, which in turn causes the render method to get called, redrawing the component with the new values.

A little more interactivity

Let’s add a text field to our application, and change the code so that we first run, it looks like this:

interactive 1

If you leave the text field blank and click the Enter button or hit the Return key, the output area should change to display this:

interactive 2

If you type the name “Zaphod” into the text field and click the Enter button or hit the Return key, the output area should change to display this:

interactive 3

Here’s the code that does this:

class Hello extends React.Component {

  constructor(props) {
    super(props)
    this.onSubmit = this.onSubmit.bind(this)
    this.state = {
      name: this.props.name,
      greeting: this.props.greeting
    }
  }
  
  render() {
    const name = this.state.name
    const greeting = this.state.greeting
    return (<div>
      <h1>Hello, {name}!</h1>
      <p>{greeting}, {name}.</p>
      
      <form onSubmit={this.onSubmit}>
        <input ref="nameTextField" type="text" placeholder="Enter your name here." />
        <button>Enter</button>
      </form>
    </div>)
  }
  
  onSubmit(event) {
    event.preventDefault()
    const nameTextField = this.refs.nameTextField
    const newName = nameTextField.value.trim()
    nameTextField.value = ""
    
    if (newName.length > 0) {
      this.setState({
        name: newName,
        greeting: "Pleased to meet you"
      })
    }
    else {
    	this.setState({
      	name: "stranger",
        greeting: "Seriously, please enter your name"
      })
    }
  }

}

Hello.defaultProps = {
  name: "stranger",
  greeting: "Please tell me your name"
}


ReactDOM.render(
  <Hello />,
  document.getElementById('app')
)

Let’s take a closer look at the code. We’ll start with the render method:

render() {
  const name = this.state.name
  const greeting = this.state.greeting
  return (<div>
    <h1>Hello, {name}!</h1>
    <p>{greeting}, {name}.</p>
      
    <form onSubmit={this.onSubmit}>
      <input ref="nameTextField" type="text" placeholder="Enter your name here." />
      <button>Enter</button>
    </form>
  </div>)
}

The only difference between this version of the render method and the previous one is the addition of a single line containing an <input> tag:

<input ref="nameTextField" type="text" placeholder="Enter your name here." />

It looks like a standard <input> tag, but it has a strange attribute called ref. That’s short for reference, and it a way for other code to access this tag. Think of it as being similar to HTML’s id attribute, but for React. We access refs that we define in JSX via the refs object, which is similar in structure to the props and state objects.

The onSubmit method isn’t all too different, either:

onSubmit(event) {
  event.preventDefault()
  const nameTextField = this.refs.nameTextField
  const newName = nameTextField.value.trim()
  nameTextField.value = ""
  
  if (newName.length > 0) {
    this.setState({
      name: newName,
      greeting: "Pleased to meet you"
    })
  }
  else {
    this.setState({
      name: "stranger",
      greeting: "Seriously, please enter your name"
    })
  }
}

Some notes:

  1. We’ve created a new constant, nameTextField, which holds a reference to the element whose ref is nameTextField — the text field into which the user enters his/her name.
  2. We fill another constant, newName, with the contents of nameTextField, trimmed of leading and trailing white space.
  3. We clear the text field.
  4. If the user entered something into the text field, newName‘s length will be greater than 0, and we change the state so that the newly-entered name becomes the value for the state key name and “Pleased to meet you” becomes the value for the state key greeting.
  5. If the user entered nothing into the text field (or entered nothing but white space into it), newName‘s length will be 0, and we change the state so that the value for the state key name is “stranger”, and “Seriously, please enter your name” becomes the value for the state key greeting.

Componentizing

So far, we’ve created a single component, Hello, for our application. For a simple tutorial app, this approach — sometimes called the Big Ball of Mud — is a workable one. You wouldn’t want to use it for an app of any appreciable size, as it becomes hard to code, manage, and maintain. Ideally, a React UI is supposed to be made up of small components that collectively form a larger whole.

Let’s break up our simple app into components as shown in the diagram below:

components

Note that in the diagram, the UI is broken into three components:

  1. Greeting: This displays the name and greeting.
  2. NameForm: This displays the form, which contains our text field and button.
  3. Hello: This contains both the Greeting and NameForm components.

Greeting and NameForm present UI components, and are thus called presentation components. Their job is to present user interface elements that are visible to the user.

Hello is used as a container for other components, and is hence called a container component. Its has a couple of jobs:

  • To act as a container for other components, Greeting and NameForm in this case, and
  • To contain the user interface state and logic for itself and its child components (again, Greeting and NameForm).

Let’s start by coding the Greeting component, one of the presentation components:

class Greeting extends React.Component {

  render() {
    const name = this.props.name
    const greeting = this.props.greeting
    return (<div>
      <h1>Hello, {name}!</h1>
      <p>{greeting}, {name}.</p>
    </div>)
  }

}

It’s a pretty simple component: it expects two props — name and greeting — and displays them appropriately. Nothing new here.

Note that Greeter doesn’t make use of any state; it simply accepts two props and displays them. It doesn’t do any “thinking”. You’ll see this approach in a lot of React code, where presentation components don’t have much logic them and a primarily concerned with the display and input of information.

Think of this as the mantra for presentation components:

youre not paid to think

Let’s now code the NameForm component, the other presentation component:

class NameForm extends React.Component {
  constructor() {
    super()
    this.onSubmit = this.onSubmit.bind(this)
  }

  render() {
    return (<div>
      <form onSubmit={this.onSubmit}>
        <input ref="nameTextField" type="text" placeholder="Enter your name here." />
        <button>Enter</button>
      </form>
    </div>)
  }
  
  onSubmit(event) {
    event.preventDefault()
    const nameTextField = this.refs.nameTextField
    const newName = nameTextField.value.trim()
    nameTextField.value = ""
    
    if (newName.length > 0) {
      this.props.onNewName(newName)
    }
    else {
      this.props.onNoName()
    }
  }

}

The only really different part is the if statement in the onSubmit method:

if (newName.length > 0) {
  this.props.onNewName(newName)
}
else {
  this.props.onNoName()
}

In the previous version of our onSubmit method, both branches made changes to the state object. This time it’s different:

  • If the user entered something into the text field (i.e. newName‘s length is greater than 0), it calls a method called onNewName, which is stored in the props object. It passes newName as an argument to onNewName.
  • If the user entered nothing or just white space into the text field (i.e. newName‘s length is 0), it calls a method called onNoName, which is also stored in the props object.

Note that both onNewName and onNoName are stored in NameForm‘s props. This means that NameForm has very little built-in logic for dealing with user input, but instead receives this logic from an outside source through its props. As with Greeter, NameForm doesn’t make use of state. Once again, this is an approach you’ll see in a lot of React code — presentation components doing as little “thinking” as possible.

Both Greeter and NameForm receive their props from their container component, Hello. Let’s look at its code:

class Hello extends React.Component {

  constructor(props) {
    super(props)
    this.state = {
      name: this.props.name,
      greeting: this.props.greeting
    }
    this.handleNewName = this.handleNewName.bind(this)
    this.handleNoName = this.handleNoName.bind(this)
  }
  
  render() {
    return (<div>
      <Greeting name={this.state.name} greeting={this.state.greeting} />
      <NameForm onNewName={this.handleNewName} onNoName={this.handleNoName} />
    </div>)
  }

  handleNewName(newName) {
    this.setState({
      name: newName,
      greeting: "Pleased to meet you"
    })
  }
  
  handleNoName() {
    this.setState({
      name: "stranger",
      greeting: "Seriously, please enter your name"
    })
  }

}

Hello.defaultProps = {
  name: "stranger",
  greeting: "Please tell me your name"
}

Let’s look at its render method first:

render() {
  return (<div>
    <Greeting name={this.state.name} greeting={this.state.greeting} />
    <NameForm onNewName={this.handleNewName} onNoName={this.handleNoName} />
  </div>)
}

Note that the <div> it returns has two component tags and nothing else:

  1. Greeting: We pass the current name and greeting to it via the attributes, which it receives as props.
  2. NameForm: We pass it two methods — handleNewName and handleNoName — via attributes, which it receives as props.

Let’s take a look at handleNewName and handleNoName:

handleNewName(newName) {
  this.setState({
    name: newName,
    greeting: "Pleased to meet you"
  })
}

handleNoName() {
  this.setState({
    name: "stranger",
    greeting: "Seriously, please enter your name"
  })
}

Note that:

  1. handleNewName does just one thing: change the state so that the value for name is set to the contents of newName, and the value for greeting is set to “Please to meet you”. Changing the state of the Hello component causes its render method to be called, which in turn causes the Greeting and NameForm components to be redrawn, which causes them to call their render methods as well.
  2. handleNoName also does just one thing: change the state so that the value for name is set to “stranger”, and the value for greeting is set to “Seriously, please enter your name”. Changing the state of the Hello component causes its render method to be called, which in turn causes the Greeting and NameForm components to be redrawn, which causes them to call their render methods as well.
  3. handleNewName and handleNoName are passed as props to NameForm, which uses their logic to perform tasks based on what the user enters or doesn’t enter into NameForm‘s text field. It appears that while Hello doesn’t present any user interface of its own, it does a lot of the “thinking”.
  4. Note that Hello‘s methods, handleNewName and handleNoName, are passed to NameForm as props with the names onNewName and onNoName. This is a naming convention used in React:
    • When defining a function that will be passed to a child component, prefix the function name with handle. A name beginning with handle implies that we’re defining a response to a specific event.
    • When passing a function to a child component as a prop, prefix the prop name with on. A name beginning with on implies that we’re calling on a defined response to a specific event.

Let’s take a closer look at the constructor:

constructor(props) {
  super(props)
  this.state = {
    name: this.props.name,
    greeting: this.props.greeting
  }
  this.handleNewName = this.handleNewName.bind(this)
  this.handleNoName = this.handleNoName.bind(this)
}

The constructor sets up the app’s initial state based on the default props. It also binds the handleNewName and handleNoName methods to the current instance, so that they can be called when they’re passed as props to the NameForm component.

Speaking of default props, here’s the function that sets Hello‘s default props:

Hello.defaultProps = {
  name: "stranger",
  greeting: "Please tell me your name"
}

That’s the complete definition for the Hello component.

We’ve just reviewed all the code in the app piece by piece. Here’s the complete code:

class Greeting extends React.Component {

  render() {
    const name = this.props.name
    const greeting = this.props.greeting
    return (<div>
      <h1>Hello, {name}!</h1>
      <p>{greeting}, {name}.</p>
    </div>)
  }

}


class NameForm extends React.Component {
  constructor() {
    super()
    this.onSubmit = this.onSubmit.bind(this)
  }

  render() {
    return (<div>
      <form onSubmit={this.onSubmit}>
        <input ref="nameTextField" type="text" placeholder="Enter your name here." />
        <button>Enter</button>
      </form>
    </div>)
  }
  
  onSubmit(event) {
    event.preventDefault()
    const nameTextField = this.refs.nameTextField
    const newName = nameTextField.value.trim()
    nameTextField.value = ""
    
    if (newName.length > 0) {
      this.props.onNewName(newName)
    }
    else {
    	this.props.onNoName()
    }
  }

}


class Hello extends React.Component {

  constructor(props) {
    super(props)
    this.state = {
    	name: this.props.name,
      greeting: this.props.greeting
    }
    this.handleNewName = this.handleNewName.bind(this)
    this.handleNoName = this.handleNoName.bind(this)
  }
  
  render() {
    return (<div>
      <Greeting name={this.state.name} greeting={this.state.greeting} />
      <NameForm onNewName={this.handleNewName} onNoName={this.handleNoName} />
    </div>)
  }

  handleNewName(newName) {
    this.setState({
      name: newName,
      greeting: "Pleased to meet you"
    })
  }
  
  handleNoName() {
    this.setState({
      name: "stranger",
      greeting: "Seriously, please enter your name"
    })
  }

}

Hello.defaultProps = {
  name: "stranger",
  greeting: "Please tell me your name"
}


ReactDOM.render(
  <Hello />,
  document.getElementById('app')
)

Looking at the entire application, note that the Hello component, as the container component, doesn’t display any UI of its own; it simply displays its child components. However, it also contains all the “smarts”, maintaining the state of the application and passing its child presentation components any information they need:

  • Hello passes data to the Greeting component, namely the name and greeting it should use, and
  • Hello passes instructions to the NameForm component, namely what it should do if the user entered a name (handleNewName) and what it should do if the user left the name text field blank or filled with white space (handleNoName).

In the meantime, the Greeting and NameForm components present their parts of the UI and do what they’re told as specified by the props passed to them.

You’ve probably noticed that this arrangement ensures that the flow of information in this application is one-way, starting at the top and going down…

flow of information

…with the top-level reactDOM.render method calling on the Hello component to render itself, and the Hello component providing data and instructions to the Greeting and NameForm components and calling on them to render themselves. The information doesn’t flow the other way — The Greeting and NameForm components don’t send any information to the Hello component, and the Hello component doesn’t send any information to the code>reactDOM.render statement. This one-way flow of information simplifies development and is a basic principle of React.

Next steps

next steps

You’ve probably suspected that this is just the beginning. You’re right — there’s only so much you can cover in a 50-minute presentation, and React is already a large topic, and it’s continuing to grow. Here are some resources you might find handy:

  • The official React site: Sooner or later, you’ll have to go to the mothership, and that’s what this site is — the official source of the React code, and home of the official documentation.
  • The React base fiddle: If you want to play around with React code in a fiddle (an online playground), this is a good place to start.
  • build with react: This site describes itself as “a periodical of tutorials and advanced articles for the react.js library”.
  • LearnCode.academy’s React.js tutorial:  If you learn better from video tutorials, you should find this one helpful. This is the first in a series of tutorials.
  • Questions tagged “reactjs” in Stack Overflow: If you have a programming problem, chances are that many other people have (or have had) the same problem, and it may have already been solved. That’s what good ol’ Stack Overflow is for!
  • The ReactJS Tampa Bay Meetup: If you’re local to the Tampa area, there’s a React meetup that meets twice monthly! They alternate between “lecture” and “lab” formats every two weeks, the group is friendly, and you’ll learn a lot.