In this lesson, we will dive into writing code. We will show you how to:

  • Check NFC availability

  • Scan NFC tags

  • Implement our game logic

Preparation#

Okay, I have launched our app in the iOS simulator. Notice that the template code generated by react-native-cli is running. Let's get rid of it.

Create src directory and a new App.js inside it. Then, write some basic JSX to center everything on the screen and print "Hello NFC".

Then, go back to the original index.js, and point the App from the original one into the new src/App.js

Detecting NFC support#

Next, we would like to detect whether the target mobile device has NFC support or not.

Let's create a hasNfc state. This state has an initial value to be null, which means we've not yet confirmed whether NFC is supported or not. Once we do, this state will be a boolean value true or false.

Then, we adjust our UI according to its value.

The next step is to actually check the NFC availability. By importing the react-native-nfc-manager, we can use the isSupported API, and it will resolve a boolean value to indicate whether the underlying device supports NFC or not.

Since the availability won't change during the whole app lifecycle, we can do this inside a useEffect hook, with no dependency. This basically simulates the componentDidMount behavior for React Class component.

And please be aware that the isSupported API (and most of the APIs for a native module) is an async function because our JavaScript code will need to cross the bridge and ask the corresponding native part for the result.

The final code looks like this:

We can see the simulator is refreshed, and the result is not supported.

Let's run the code on a real iOS device. All recent iPhones from iPhone 8 all support NFC.

Once we confirm that the device does support NFC, we can do the native module initialization by calling the NfcManager.start function.

Quick review: We just used the isSupported API to check the NFC availability, and if the device supports it, we then call start to initialize our NFC native module.

It's time to start our actual Game component. Let's quickly create a src/Game.js by copying the existing code and removing the unnecessary parts.

Then, use this Game component in our App.js when NFC is available.

Scanning for our first tag#

Now we're finally ready to scan NFC tags.

First, import NfcManager and NfcEvents from react-native-nfc-manager.

Then, use setEventListener to listen to NfcEvents.DiscoverTag event. For now, we just log the message to the console. A small trick here is to use console.warn for logging rather than console.log, so we can see the yellow screen UI popup without enabling the debugger.

The actual tag scanning is through the registerTagEvent API. Once it discovers any NFC tags, the native side will emit DiscoverTag event with the tag data to the JavaScript side.

Okay, let's test it on a real device. Please remember, the NFC antenna for an iPhone is on the top of the device, so the proper position to scan a tag is probably like this picture.

Now let's scan a tag.

Cool, something indeed happened. We can see the iOS NFC prompt pop up once we hit our start button, and the icon changes when the tag is scanned.

Let's see what's in our warning message here. It is an object that contains a ndefMessage property, which is an array. The object in this array contains properties such as payload, type, tnf, and id:

Don't worry about them now; we will deep dive into these properties in our next app.

Next, let's move the event listener setup and clean up code into a useEffect hook.

Game logic#

It's about time to write our game logic.

The objective of our game is to calculate how much time a player needs to scan five NFC tags. The shorter time means a better score.

First, create a start state to track when a player hits the start button. Our useEffect hook should depend on this start state and re-run the hook logic when it is changed. Because in such a case, it basically means the user re-started the game.

Then, we use a variable called count inside the closure of our hook to track the remaining count left for a player to scan.

Once the count becomes 0, the game is finished, and we should stop the NFC scanning by calling NfcManager.unregisterTagEvent and calculate the total elapsed time.

And, of course, we will have to also render the duration into React elements.

Before testing it on a real device, we notice one thing. That is, during gameplay, the user cannot see any UI updates because the iOS default scan UI is on top of our Game component.

In order to provide users some messages while they play the game, we can use NfcManager.setAlertMessageIOS to update the iOS NFC scan prompt.

Okay, let do a final test on a real device again.

Cool, it works pretty well. By the way, my personal best record is about five seconds. See if you can beat me!

At this point, your App.js should look like this:

Here's the Game.js:

Start a new discussion. All notification go to the author.