If you spend enough time interacting with digital accessibility
practitioners, you may encounter the phrase “equivalent experience.”
This saying concisely sums up a lot of the philosophy behind
accessibility work.
Our industry tends to place a lot of focus on how, often at the expense of why.
For accessibility-related concerns, it is vital to learn about the
history, and lived experiences of disabled people as a context for
understanding the need for design and code created with access in mind.
This
is the first of two articles on the topic of equivalency, and how it
relates to digital accessibility. It will help us define what an
equivalent experience is. Once we have a common understanding
established, I’ll then discuss how to go about implementing equivalent
experiences for common accessibility-related issues.
The State Of Things
The
truth of the matter is that even though we live in a multi-device world
full of smartphones, augmented reality, voice assistants, and IoT smart
sensors, our default is still predominately:
Visual,
large screen,
fast connection,
powerful computer and display,
male,
white,
wealthy,
young,
Western,
technologically-literate,
and abled.
This is reflective of the biases that are inherent in how we design, develop and grow products.
The
previous list may not be the most comfortable thing to read. If you
haven’t closed the browser tab already, take a moment to consider your
daily workflows, as well as who your coworkers are, and you’ll begin to
understand what I’m getting at.
At its core, delivering an equivalent experience is ultimately about preserving intent — with the intent being the motivating force behind creating a website or web app and all the content and features it contains.
This
translates to making the meaning behind every interaction, every
component, every photo or illustration, every line of code being
understandable by the widest range of people, regardless of their device
or ability.
What Isn’t An Equivalent Experience?
Showing
examples of what something is not can be a way to help define it. For
equivalent experiences, an example would be a web app geared towards use
by the general public not having a mobile breakpoint.
With this example, everyone using a device with a small display is
forced to pinch, pan, and zoom to get what they need. Here, the burden
is placed on anyone whose only crime was using a smartphone.
Most
likely, whoever conceived of, designed, and developed this didn’t stop
to think about circumstances other than their own. In this sort of
(unfortunately still all too common) scenario, I all but guarantee that
the web app looks great on the laptops or desktops of the designers and developers who made it.
People using a smartphone to access this website are victims of
circumstance. The extra effort someone needs to do to get it to work
indirectly communicates that they weren’t a priority, and therefore not
valued. If you’ve used the web for any significant portion of time, I’m
willing to bet this, or a similar experience has happened to you.
This
example is also a hop, skip, and a jump away from another common, yet
serious accessibility issue we often don’t consider: screen zooming:
Screen Zooming
Screen
zooming is when someone is prevented from being able to zoom their
displays and make text larger—many native mobile apps are guilty of
this. When you disallow this sort of behavior, you’re telling
prospective users that unless they have vision similar to you, you
aren’t interested in them being able to use your app.
For this scenario, a gentle reminder that we will all get older, and with aging comes a whole host of vision-related concerns.
This might be a little difficult of a concept to grasp at first. Let’s use this Rube Goldberg machine made by Joseph Herscher to pass the pepper to his dinner guest to compare.
To pass the pepper, the machine, sends it through an elaborate system
of weights, counterweights, ramps, rolling objects, catapults,
guillotines, burners, timers, carousels, etc. — all constructed from
commonly found kitchen items. While this setup will technically ensure the pepper is passed, it is an annoying, overwrought, time-intensive process.
Many digital experiences are a lot like a Rube Goldberg machine when it comes to accessibility. Since accessibility issues are so prevalent, many forms of assistive technology provide a large suite of features to allow their user to work around common obstacles.
Unfortunately,
discovering obstacles, and then figuring out and activating the
appropriate combination of features to overcome them can take a
disproportionate amount of time and effort.
To say it another way:
A simple click on a button for an abled person may take far more time
and effort for a disabled person, depending on how the button has been
made.
Chilling Effects
Frustratingly, the
extra time and effort a disabled person has to put into operating a
technically accessible experience may feed back into their disability
condition(s). For example, the presence of a motor control disability such as arthritis may make the overall experience even more taxing. Cognitive accessibility concerns
are also another important thing to consider. What may seem easy to
understand or intuitive to use for one person may not be for another.
This is especially prevalent in situations where there is:
Cognitive
accessibility isn’t an abstract concern, either. Poor user interface
design that ignores the circumstances of the end user and dumps too much
cognitive load onto them can have very real, very serious consequences.
Compounding Effects
These factors are not mutually exclusive. Proponents of Spoon Theory
know that inaccessible experiences conspire to sap a person’s mental
and physical energy, leaving them exhausted and demotivated. Worse,
these sorts of scenarios are often more than just a person perpetually
operating at a diminished capacity.
Frustrating digital experiences can lead to a person abandoning them outright, internalizing the system’s fault
as their own personal failure. This abandonment may also translate to a
person’s willingness and ability to operate other digital interfaces.
In other words: the more we turn people away, the more they’ll stop
trying to show up.
Consistency
For some, assistive technology
can mean specialized browser extensions. These micro-apps are used to
enhance, augment, and customize a browsing experience to better suit
someone’s needs. Damien Senger, digital designer, uses a browser extension called Midnight Lizard
to enforce a similar experience across multiple websites. This helps
them “to focus on the content directly and to limit having too big
differences between websites. It is also helping me to avoid too harsh
color contrasts that are really uncomfortable.“
Damien also
writes, “Often websites are really difficult to read for me because
either of the lack of consistency in the layout, too narrow lines or
just not enough balance between font size and line height. Related to
that, color can create a lot of unhelpful distraction and I am
struggling when too harsh contrast is nearby text.”
Consistent application of color can also help communicate what elements can be interacted with, so long as it is not just the color alone that indicates interactivity.
Ensure
that text content is written using text (not presented as an image),
allowing it to be read aloud, restyled, and reformatted.
Understand that branding includes how something behaves, responds, and reacts in addition to how it looks.
In
addition, Damien also augments their browsing experience by using ad
blocking technology “not only for ads but to block animations or content
that are too distracting for my ADHD.”
It’s
not too difficult to imagine why distracting and annoying your users is
a bad idea. In the case of ads, the industry is unregulated, meaning
that rules to prohibit
ADHD, migraine, and/or seizure-triggering animations aren’t honored.
Through this lens, an ad blocker is a form of consumer self-defense.
Kenny Hitt also chimes in
about ads: “…regardless of the platform, the thing that annoys me most
are websites with ads that essentially cause the site to constantly auto
update. This prevents me as a screen reader user from reading the
content of those websites.”
Again, a lack of regulation means the user must take measures into their own hands to keep the experience equivalent.
A
lack of an equivalent experience translates directly to lost
opportunity. Many individuals I spoke with mentioned that they’d abandon
a digital experience that was inaccessible more often than not. Brian Moore
mentions, “there are web sites where I like their products a lot but
won’t buy them because the site itself is such a struggle, and attempts
to reach out have met with either silence or resistance to taking any
action.”
Brian cites the Fluance website
as the most recent example. The bugs present in its shopping user flows
prevents him from buying high-end consumer audio equipment.
Fluance’s
entire web presence exists to sell products. While updating a website
or web app to be accessible can be an effort-intensive process, it would
definitely be in Fluance’s best interest to make sure its checkout user
flow is as robust as it could be.
High-volume sales and a large catalog don’t protect your Amazon account
As we head into peak season, it’s easy for large third-party Amazon sellers to be over-confident about their position with Amazon.
Many assume that their high revenue, large order volume or wide
selection of offers protects them from enforcement actions by Amazon
Seller Performance.
In other cases, sellers have had long-time personal relationships
with account managers, sales folks or even executives in Amazon’s
Seattle offices. These person-to-person interactions must offer some
degree of protection, right?
Unfortunately, the larger Amazon becomes, the less any of these factors truly help a third-party seller:
Broad selection means nothing. Unique selection, however, is seen as
a virtue. If you sell items that have a lot of other sellers on them,
Amazon is not concerned about losing you as a seller. Someone else is
already providing your inventory on the platform.
Similarly, a high volume of orders or big revenue numbers don’t
protect you. Amazon can get those same sales from other third-party
sellers or vendors.
Personal relationships are becoming less important as the company
gets bigger. Many sellers make the mistake of believing that an “account
manager” – who is really in sales at Amazon – can protect their
account. That’s simply not true. These sales folks are responsible for
bringing in new sellers and product selection. They do care about their
accounts, since they are goal based on revenue. But they don’t have the
power to make enforcement issues go away. Strategic account managers
sometimes can help, but their arguments to Seller Performance must be
based on facts – not your account’s size or selection.
What do Amazon executives care about? They love feel-good stories that prop up Amazon’s reputation:
Amazon executives like seller-owned brands that sell exclusively on
Amazon and spend money for PPC, Early Reviewer, etc. These sellers bring
in sales that Amazon wouldn’t have otherwise.
Amazon executives like sellers who bring unique products to the
platform, through exclusive relationships with manufacturers,
wholesalers and the like.
Being a unique brand or having exclusive offers on Amazon still
won’t prevent Seller Performance from taking action if it perceives your
products or customer service as poor or risky.
What is the takeaway for large third-party Amazon sellers?
Invest in strategies that ensure your Amazon customers receive
excellent-quality products and fantastic service with every transaction.
That will protect your account sooner than volume, catalog size or even
Amazon relationships.
Brand building is an essential element as an Amazon FBA seller, but that
doesn’t just mean Amazon. You can work on every aspect of your business
and use the resources to slowly scale your business beyond an online
store into retail space. And you are not alone. Many product-based
brands want to be carried by major retailers. The question is how do you
get your products into stores?
Amazon has already conquered the e-commerce space and is the leading
online retailer. But here is the truth; despite the dominance of online
stores like Amazon, physical stores still find their way to the top of
that pile. The endless benefits retailers offer should be part of your
business scaling plan.
In today’s climate, expanding your business past the online space
will significantly increase your sales through increased customer reach.
Another benefit of targeting brick-and-mortar stores is having a
separate income stream from your Amazon business. Running an Amazon FBA
business comes at a risk. With Amazon policies changing now and then,
there is no telling when you will run into problems like Amazon
suspensions.
If your products are selling at a physical store, it means reduced
risk because your goods can continue selling as you sort out your Amazon
suspension issues. But the most significant benefit of targeting
physical stores is increasing brand recognition and authority.
This article will outline how you can sell in retail stores as the next step in your selling journey.
What do retailers want to see when you approach them to sell your products in their stores?
There is a thrill in seeing your products on the shelf spaces of
brick-and-mortar stores. Think about your beautiful packaging sparkling
in front of a customer’s eyes!
With so much competition in the physical retail space,
only a select few will achieve their retail goals. Landing your product
in a major physical store isn’t an easy feat. It will take time and
persuasion, and you must demonstrate to the retailer why your product is
worth the shelf space.
So, what do retailers want to see before they determine if they’ll carry your product in their store?
#1 Proof of sale data
Retail stores face many challenges like
paying overhead for rent, store fixtures, employees, utilities, signage,
and furnishings.
Physical stores also operate on thin
profit margins, and that’s why a store will have no problem
discontinuing a product that isn’t generating enough sales.
So, when you approach a store, the first
thing they want to see is data showing that you have had significant
sales success online.
Ideally, if your products are not selling
on Amazon, what makes you think it will be any different with a
physical store? Prove your worth for the retail market.
#2 Showcase stunning branding and product portfolios
For physical stores, branding is
everything. A physical store relies on foot traffic to make sales. A
product must first attract buyers’ attention before they buy. Beautiful
branding is something you need to work on.
Retail stores want to see a brand
portfolio of multiple products that could naturally sell in their
stores. Think about branding in a systematic approach and rebrand some
of your most essential products specifically for retail if they aren’t
up to par or if they need a retail refresh.
#3 Effective packaging
Fact: Packaging drives purchasing decisions more than TV ads, online reviews, and customer recommendations.64% of customers will sometimes buy a product they haven’t even heard of because of the packaging.
Packaging is different for products sold
online and in physical stores. At the moment, you might not have
adequate retail shelf packaging for products you sell online since you
never needed one.
But before you approach a physical store,
you must consider packaging. First impressions count. Your goal is to
be catchy. It’s common for customers to stop and stare at products. You
must convince the retailer that your product can do that. A professional
design will make your product worth its space.
Knowledge of marketing strategies
Marketing strategies like endcaps and point-of-purchase displays are
vital in retail stores. An average shopper can be exposed to more than
20,000 products per shopping trip. Because of this competition, brands
need to ensure that their products stand out and attract customers to
make a purchase. Strategies like endcap displays, therefore, come into
play.
A point of purchase display (POP display) is a custom display
showcasing products outside their natural habitat but in a retail
setting. POP displays are great for promoting a product and showcasing
special offers and deals. A POP display also helps educate a potential
customer on the offering and brand details.
An end cap display allows one to create visually appealing spaces
that draw in shoppers. You must demonstrate to the retail store that you
understand these strategies and that your product can effectively fit into and work in their retail store footprint.
What are the challenges sellers may face getting their products into retail stores?
Getting into retail stores is challenging, and only a few online
sellers make the cut. Here are some of the challenges most sellers face
when trying to get into retail:
Relationships with buyers in the chains: If you
can’t develop a good relationship with buyers, there is no way a retail
store will carry your products. Buyers are interested in only one thing-
growing the total category value. If you can’t show them you understand
their strategy, they will go with someone who does.
Relationships with the right buyers in the right departments: To get into retail, you must identify the right buyers to pitch to.
Difficulty knowing whether to launch your existing brand or create a diffusion brand with
a different price point and adjusted branding: A diffusion brand is the
second line of product that is supposed to appeal to a different target
market. A diffusion brand could work when getting into retail to target
consumers who will have the product flying off the shelves. But then,
it could also overshadow your leading brand creating more problems.
Understanding how to set up your vendor number: A
vendor number is given by a retail store if they agree to carry your
product. However, most Amazon sellers don’t know how to set up a vendor
number or what documents are required.
Capital to manufacture enough product for retail orders or
financing to underwrite the orders: Getting a retail store to carry
your product is one thing, and ensuring you have enough products is
another. Most Amazon sellers
don’t think about this when approaching retail stores and end up with
zero products on the shelves because they don’t have the capital to
handle large orders.
Logistics capabilities: You have to nail down
everything, including how to manage all your logistics at the lowest
cost, so you are not incurring losses in the end.
Tips on how to get your winning online products into retail stores
There are over 1 million retail establishments
across the United States, and retail stores have grown almost 4%
annually since 2010. In 2020, there were 328,208 brick and mortar retail
stores in the United States.
Online retail leaders are less than 10%.
It’s no longer an in-store vs. online debate. The narrative has
changed. So, here are ways to get into retail as an online seller.
#1 Research the competition
To make it in the retail business, you need to know where your product sits when it comes to your competition.
Who is your competition?
What products are they selling?
How much are their products selling for?
When researching the competition, we
don’t mean going to Amazon. Researching competition on Amazon is useless
because you are targeting retailers in this case.
Never underestimate the value of
competitor data. Walking into a store, you are targeting will expose you
to brands selling similar products. You can then establish their
strengths and weaknesses, so you know how to make your product stand out
from theirs.
#2 Work on your branding
Being an e-commerce-ready brand doesn’t mean that you are a retail-ready brand. But if you are retail-ready, then you are also e-commerce-ready.
Branding is everything in the retail
industry. While growing a brand is not a one-time process, you need to
work on your branding before you start selling. Branding, in this case,
is all about the colors and images you choose to represent you to the
public.
Have good branding for your website,
social media pages, lifestyle images, and packaging. Your branding needs
to be cohesive and show a preview of your products.
#3 Product data and marketing plan
To get into retail, you must clarify that
your product has a unique selling point that will cause it to fly off
the shelves. You must also understand your target audience, estimated
demand, and suggested retail product price.
Highlight your promotional and marketing
plans to the retailer to prove to the buyer that you are invested in
helping them sell your product.
#4 Understand the buyer’s category mission and vision
What is the overall strategy of the buyer
or retailer? How will you position your brand to align with their
vision and mission for that category?
For instance, if the objective of the
category is to provide responsible soft drink options, you have to
determine how your product meets that pillar and whether your target
audience is aligned with the same.
#5 Show you understand the retailer’s customer needs
Customer needs change from time to time
and so do specific categories. For a retailer to carry your products,
you must convince them you know what their customers in a particular
category are looking for. Doing so shows that you know the category
inside out.
Summary
Getting your products into retail stores
is one of the best ways of expanding your reach. It is also a great way
of having another stream of income. Amazon is unpredictable, and you
never know what might happen in the future.
To keep your products moving, even when dealing with Amazon issues
like suspensions, it helps if you have another way to reach customers.
To get into retail, explain to the retailer the reasons why your product
will fly off the shelves and what your product has that makes it
unique.
That said, there has never been a better time to start your retail
journey than now. If you’re looking for more info about your retail
sales journey, head to projectretail.com
If your winning Amazon ASINs belong in retail stores, don’t struggle alone.
As Spring nears, it’s a great time to start cleaning after a long
winter to prepare for sunny skies ahead. Spring cleaning is typically
something we do every year, some of us a few times a year, to keep our
homes in tip-top shape through the seasons.
Much like the spring cleaning of your home, your Amazon FBA business
requires regular spring cleaning or hygiene to run smoothly all year
round. Now is as great a time to develop a step-by-step hygiene routine
to maintain your account in good standing, now and for the future.
As a new Amazon seller, you may not have much awareness about Amazon
seller account health because your focus to date is growing your FBA
business. Without routine hygiene, you may not know that your FBA
business can be at severe risk.
This article will detail the most vital aspects of maintaining Amazon
account hygiene so you can run a smooth and successful FBA business.
What does Amazon seller account hygiene mean?
Selling on Amazon is a privilege, and with that privilege comes the
responsibility to maintain your Amazon account in good health. As an FBA
business owner, you must understand the privilege Amazon extends so
that you prioritize account health to avoid account suspension or
closure.
Your Amazon seller central account contains a section entirely
dedicated to account health. In this section of your account, you’ll
find a slew of account metrics to keep your account in good standing and
discover account level warnings that require your attention.
To access your Amazon Account Health
page in Amazon Seller Central, open the performance tab and choose
Account Health. Select Seller Central > Performance Menu > Account
Health. Once in this section, you’ll discover an overview of
compliances with Amazon policies.
Amazon seller account health is composed of three metrics:
Customer Service Performance
Product Policy Compliance
Shipping Performance
On the Amazon Health page, you’ll be able to review negative feedback, and chargeback claims.
Where to begin with Amazon account hygiene
Amazon account hygiene
requires ongoing attention to stay on top of policy and account health.
When looking to create a systematic process for account hygiene, it’s a
good idea to begin with the foundation within your Amazon account.
To start, focus on your catalog of products as the priority. From
there, navigate any stranded inventory and negative feedback. While this
may sound simple, you’ll want to develop a practical process that
ensures you consistently maintain good account hygiene.
Step 1 – Review Your Entire Catalog
As a growing FBA business, you’re likely to consistently add products
to your catalog. That’s excellent news in terms of your ability to
scale. Unfortunately, adding more products can mean that sellers
inadvertently overlook older products not intended for sale.
Often the addition of new products doesn’t always come with the
intention of selling these products. Sellers frequently add new products
to understand if they meet ungating requirements or specific
permissions and compliances. But, if the product remains on the Manage
Inventory Page, Amazon fully believes you intend to sell that product.
If for whatever reason, you receive an IP complaint (Intellectual
Property Violation or Restricted Product Warning,) you could face a
severe ASIN violation
without your knowledge. If you were to list this product in the future
and were not aware of the ASIN violation, you could experience a
negative score against your account.
The Solution
Ensure the deletion of all products from inventory that you have no
intention to sell. It’s a simple fix but often overlooked as you begin
to scale your FBA business. The added benefit of deleting products you
don’t intend to sell is that your inventory performance score will
improve. The inventory performance score is vital to the quantity of
inventory you can send to Amazon; therefore, a positive score is
critical.
Step 2 – Deal With Stranded Inventory
If not careful, you can locate a substantial amount of stranded
inventory and a stranded inventory Amazon FBA inventory error in your
Amazon account. Stay on top of stranded inventory to keep your account
in good health and to maintain a positive inventory performance score.
The Solution
How to fix stranded inventory on Amazon? Go into the stranded
inventory page of Amazon Seller Central and reconcile each ASIN one by
one. This may mean that you remove stranded inventory to your warehouse
or home or that you have it disposed of by Amazon.
Removing stranded inventory can require a refresh of your inventory screen, a call to Seller Support,
or an appeal. While appeals are common, it’s best to avoid the Amazon
stranded inventory listing error and inventory languishing in this area.
Step 3 – Check The Feedback In Your Storefront
Amazon seller feedback
is a metric that evaluates your selling performance. It’s available for
Amazon customers and can be left when a customer returns an order or
through the feedback page on Amazon.
Negative and neutral reviews can be mistakenly entered into this area
by customers. A negative review can negatively affect your feedback
performance score when that happens.
The Solution
Previously sellers could request negative reviews be removed from the
feedback section by clicking a report feedback button. Today, sellers
must open a case file for each incorrect feedback to have them removed.
Remove all negative or neutral reviews from this area to increase your
performance score and continue selling without issue.
Summary
You’ll want to check your Amazon Account Health dashboard on an
ongoing basis and add this task to your daily standard operating
procedures. Regularly address any ASIN violations or other policy
violation warnings in your account health dashboard to maintain good
account hygiene. Avoiding problems out of fear only increases risk and
can make appeals more challenging if appeals are required.
The instances of poor account health and stranded deep inventory
sneak up on sellers, especially if they don’t know where to look or how
to address warnings and violations. It’s good to work with an account
specialist who can provide a comprehensive violation review and an
action plan to address each one.
We can’t stress enough the importance of regular Amazon account
hygiene. It’s too easy to sell on the platform and ignore this crucial
aspect of business, especially as sales continue to roll in. Create an
ongoing hygiene review within your Amazon account, like your spring
cleaning regime.
How do you perform routine Amazon account hygiene? Let us know in the comments.
Need help with an ASIN appeal or an Amazon seller account health issue?
Often
you need two different sets of navigation stacks for pre and post user
authentication. Usually, to see more content, you have to be
authenticated in some way. Let’s look at how to mount and unmount
navigation stack based on a met condition in React Native.
In this article, we are going to walk through mounting and unmounting of navigation routes
in React Native. An expected behavior of your app is that once the
authentication condition is met, a new set of navigation routes are
available only to logged-in users, while the other screens which were
displayed before authentication is removed and can’t be returned to
unless the user signs out of the application.
For security in your app, protected routes provide you with a way to
only display certain information/content on your app to specific users,
while restricting access from unauthorized persons.
We will be working with Expo for this
project because it’ll help us focus on the problem at hand instead of
worrying about a lot of setups. The exact same steps in this article
could be followed for a bare React Native application.
You need some familiarity with JavaScript and React Native to follow through with this tutorial. Here are a few important things you should already be familiar with:
Custom components in React Native (how to create components, receive, pass, and use props in a component). Read more.
If you’re new to using expo and don’t know how to install expo, visit the official documentation. Once the installation is complete, go ahead to initialize a new React Native project with expo from our command prompt:
expo init navigation-project
You will be presented with some options to choose how you want the base setup to be:
In our case, let’s select the first option to set up our project as a
blank document. Now, wait until the installation of the JavaScript
dependencies is complete.
Once our app is set up, we can change our directory to our new
project directory and open it in your favorite code editor. We need to
install the library we will be using for AsyncStorage and our navigation libraries. Inside your folder directory in your terminal, paste the command above and choose a template (blank would work) to install our project dependencies.
Let’s look at what each of these dependencies is for:
@react-native-community/async-storage
Like localStorage on the web, it is a React Native API for persisting data on a device in key-value pairs.
@react-native-community/masked-view, react-native-screens, react-native-gesture-handle
These dependencies are core utilities that are used by most navigators
to create the navigation structure in the app. (Read more in Getting started with React Native navigation.)
@react-navigation/native
This is the dependency for React Native navigation.
@react-navigation/stack
This is the dependency for stack navigation in React Native.
To start the application use expo start from the app
directory in your terminal. Once the app is started, you can use the
expo app from your mobile phone to scan the bar code and view the
application, or if you have an android emulator/IOS simulator, you can
open the app through them from the expo developer tool that opens up in
your browser when you start an expo application. For the images examples
in this article, we will be using Genymotions to see our result.
First, we imported the things we need from the React Native library, namely, View, Text, Button, TextInput. Next, we created our functional component WelcomeScreen.
You’ll notice that we imported the StyleSheet from React Native and used it to define styles for our header and also our <TextInput />.
Lastly, we export the WelcomeScreen component at the bottom of the code.
Now that we are done with this, let’s get this component to function as expected by using the useState
hook to store the values of the inputs and update their states anytime a
change happens in the input fields. We will also bring import the useCallback hook from React as we will be needing it later to hold a function.
First, while we are still in the WelcomeScreen component, we need to import the useState and useCallback from React.
Next, we need to modify our <TextInput /> fields so that the get their value from their respective states and update their state when the value of the input is updated:
We made the value of each of the text inputs to point to their respective states.
We added the onChangeText handler to our text inputs. This fires up anytime a new value is entered or deleted from the input fields.
We called our onInputChange function which accepts two arguments:
The current value is supplied by the onChangeText handler.
The setter of the state that should be updated (for the first input field we pass setEmail and the second we pass setPassword.
Finally, we write our onInputChange function, and our function does only one thing: It updates the respective states with the new value.
The next thing we need to work on is the onUserAuthentication() function with is called whenever the button for the form submission is clicked.
Ideally, the user must have already created an account and login will
involve some backend logic of some sort to check that the user exists
and then assign a token to the user. In our case, since we are not using
any backend, we will create an object holding the correct user login
detail, and then only authenticate a user when the values they enter
matches our fixed values from the login object of email and password that we will create.
Here’s the code we need to do this:
...const correctAuthenticationDetails ={
email:'demouser@gmail.com',
password:'password'}constWelcomeScreen=()=>{...// This function gets called when the `AUTHENTICATE` button is clickedconstonUserAuthentication=()=>{if(
email !== correctAuthenticationDetails.email ||
password !== correctAuthenticationDetails.password
){alert('The email or password is incorrect')return}// In here, we will handle what happens if the login details are // correct}...return(...)}...
One of the first things you’ll notice in the code above is that we defined a correctAuthenticationDetails (which is an object that holds the correct login details we expect a user to supply) outside of the WelcomeScreen() functional component.
Next, we wrote the content of the onUserAuthentication() function and used a conditional statement to check if the email or password held in the respective states does not match the one we supplied in our object.
If you would like to see what we have done so far, import the WelcomeScreen component into your App.js like this:
Open the App.js file and put this replace the entire code with this:
Using Context API, we do not need to install any additional library
into ReactJS, it is less stressful to set up, and is one of the most
popular ways of handling global state in ReactJS. For lightweight state
management, it is a good choice.
The AuthContext we just created holds the loading state value and the userToken state values. Currently, in the createContext we declared in the code-block above, we didn’t initialize any default values here so our context is currently undefined. An example value of the auth context could be {loading: false, userToken: 'abcd}
The AuthState.js file holds our Context API logic
and their state values. Functions written here can be called from
anywhere in our app and when they update values in state, it is updated
globally also.
First, let’s bring in all the imports we will need in this file:
We imported the useState() hook from ReactJS to hold our states, we imported the AuthContext
file we created above because this is where our empty context for
authentication is initialized and we will need to use it as you’ll see
later on while we progress, finally we import the AsyncStorage package (similar to localStorage for the web).
AsyncStorage is a React Native API that allows you to persist data offline over the device in a React Native application.
...constAuthState=(props)=>{const[userToken, setUserToken]=useState(null);const[isLoading, setIsLoading]=useState(true);constonAuthentication=async()=>{constUSER_TOKEN="drix1123q2"await AsyncStorage.setItem('user-token',USER_TOKEN);setUserToken(USER_TOKEN);
console.warn("user has been authenticated!")}return(<AuthContext.Provider
value={{
onAuthentication,}}>{props.children}</AuthContext.Provider>)}exportdefault AuthState;
In the code block above here’s what we did:
We declared two states for the userToken and isLoading. The userToken state will be used to store the token saved to AsyncStorage, while the isLoading state will be used to track the loading status (initially it is set to true). We will find out more about the use of these two states as we proceed.
Next, we wrote our onAuthentication() function. This function is an async function that gets called when the login button is clicked from the welcomeScreen.jsx
file. This function will only get called if the email and password the
user has supplied matches the correct user detail object we provided.
Usually what happens during authentication is that a token is generated
for the user after the user is authenticated on the backend using a
package like JWT, and this
token is sent to the frontend. Since we are not going into all of that
for this tutorial, we created a static token and kept it in a variable
called USER_TOKEN.
Next, we use the await keyword to set our user token to AsyncStorage with the name user-token. The console.warn() statement is just used to check that everything went right, you can take it off whenever you like.
Finally, we pass our onAuthenticated function as a value inside our <AuthContext.Provider> so that we can access and call the function from anywhere in our app.
screens > preAuth > welcomeScreen.js
First, import useContext from ReactJS and import the AuthContext from the AuthContext.js file.
Now, inside the welcomeScreen() functional component, let’s use the context which we have created:
...constWelcomeScreen=()=>{const{ onAuthentication }=useContext(AuthContext)constonUserAuthentication=()=>{if(
email !== correctAuthenticationDetails.email ||
password !== correctAuthenticationDetails.password
){alert('The email or password is incorrect')return}onAuthentication()}return(...)}...
In the above code block, we destructured the onAuthentication function from our AuthContext and then we called it inside our onUserAuthentication() function and removed the console.log() statement which was there before now.
Right now, this will throw an error because we don’t yet have access to the AuthContext. To use the AuthContext anywhere in your application, we need to wrap the top-level file in our app with the AuthState (in our case, it is the App.js file).
Go to the App.js file and replace the code there with this:
We’ve come so far and we’re done with this section. Before we move
into the next section where we set up our routing, let’s create a new
screen. The screen we are about to create will be the HomeScreen.js file which is supposed to show up only after successful authentication.
Go to: screens > postAuth.
Create a new file called HomeScreen.js. Here’s the code for the HomeScreen.js file:
For now, the logout button has a dummy console.log() statement. Later on, we will create the logout functionality and pass it to the screen from our context.
We imported the createStackNavigator from the @react-navigation/stack which we are using for our stack navigation. The createStackNavigatorProvides
a way for your app to transition between screens where each new screen
is placed on top of a stack. By default the stack navigator is
configured to have the familiar iOS and Android look & feel: new
screens slide in from the right on iOS, fade in from the bottom on
Android. Click here if you want to learn more about the stack navigator in React Native.
We destructured Navigator and Screen from the createStackNavigator().
In our return statement, we created our navigation with the <Navigator/> and created our screen with the <Screen/>. this means that if we had multiple screens that can be accessed before authentication, we will have multiple <Screen/> tags here representing them.
Finally, we export our PreAuthNavigator component.
Let us do a similar thing for the postAuthNavigator.js file.
As we see in the code above, the only difference between the preAuthNavigator.js and the postAuthNavigator.js is the screen being rendered. While the first one takes the WelcomeScreen, the postAuthNavigator.js takes the HomeScreen.
To create our AppNavigator.js we need to create a few things.
Since the AppNavigator.js is where we will be
switching and checking which route will be available for access by the
user, we need several screens in place for this to work properly, let’s
outline the things we need to create first:
TransitionScreen.js
While the app decides which navigation it is going to mount, we want a
transition screen to show up. Typically, the transition screen will be a
loading spinner or any other custom animation chosen for the app, but
in our case, we will use a basic <Text/> tag to display loading….
checkAuthenticationStatus()
This function is what we will be calling to check the authentication
status which will determine which navigation stack is going to be
mounted. We will create this function in our context and use it in the Appnavigator.js.
Now, let’s go ahead and create our TransitionScreen.js file.
Our
transition screen is just a simple screen that shows loading text. We
will see where to use this as we proceed in this article.
Next, let us go to our AuthState.js and write our checkAuthenticationStatus():
context > authContext >AuthState.js
import React,{ useState, useEffect }from'react';import AuthContext from'./AuthContext';import AsyncStorage from'@react-native-community/async-storage';constAuthState=(props)=>{const[userToken, setUserToken]=useState(null);const[isLoading, setIsLoading]=useState(true);...useEffect(()=>{checkAuthenticationStatus()},[])constcheckAuthenticationStatus=async()=>{try{const returnedToken =await AsyncStorage.getItem('user-toke n');setUserToken(returnedToken);
console.warn('User token set to the state value)}catch(err){
console.warn(`Here's the error that occured while retrievin g token: ${err}`)}setIsLoading(false)}constonAuthentication=async()=>{...}return(<AuthContext.Provider
value={{
onAuthentication,
userToken,
isLoading,}}>{props.children}</AuthContext.Provider>)}exportdefault AuthState;
In the code block above, we wrote the function checkAuthenticationStatus(). In our function, here’s what we are doing:
We used the await keyword to get our token from AsyncStorage. With AsyncStorage, if there’s no token supplied, it returns null. Our initial userToken state is set to null also.
We use the setUserToken to set our returned value from AsyncStorage as our new userToken. If the returned value is null, it means our userToken remains null.
After the try{}…catch(){} block, we set isLoading to false because the function to check authentication status is complete. We’ll need the value of isLoading to know if we should still be displaying the TransitionScreen
or not. It’s worth considering setting an error if there is an error
retrieving the token so that we can show the user a “Retry” or “Try
Again” button when the error is encountered.
Whenever AuthState mounts we want to check the authentication status, so we use the useEffect() ReactJS hook to do this. We call our checkAuthenticationStatus() function inside the useEffect() hook and set the value of isLoading to false when it is done.
Finally, we add our states to our <AuthContext.Provider/> values so that we can access them from anywhere in our app covered by the Context API.
Now that we have our function, it is time to go back to our AppNavigator.js and write the code for mounting a particular stack navigator based on the authentication status:
navigation > AppNavigator.js
First, we will import all we need for our AppNavigator.js.
In the above block of code, here’s an outline of what we did:
We created a stack navigator and destructured the Navigator and Screen from it.
We imported the userToken and the isLoading from our AuthContext
When the AuthState mounts, the checkAuthenticationStatus() is called in the useEffecct hook there. We use the if statement to check if isLoading is true, if it is true the screen we return is our <TransitionScreen /> which we created earlier because the checkAuthenticationStatus() function is not yet complete.
Once our checkAuthenticationStatus() is complete, isLoading is set to false and we return our main Navigation components.
The NavigationContainer was imported from the @react-navigation/native. It is only used once in the main top-level navigator. Notice that we are not using this in the preAuthNavigator.js or the postAuthNavigator.js.
In our AppNavigator(), we still create a stack navigator. If the userToken gotten from our Context API is null, we mount the PreAuthNavigator, if its value is something else (meaning that the AsyncStorage.getItem() in the checkAuthenticationStatus() returned an actual value), then we mount the PostAuthNavigator. Our conditional rendering is done using the ternary operator.
Now we’ve set up our AppNavigator.js. Next, we need to pass our AppNavigator into our App.js file.
At this point, our authentication and route selection process is
complete. The only thing left for our app is to add the logout
functionality.
The logout button is in the HomeScreen.js file. We passed an onLogout() function to the onPress attribute of the button. For now, we have a simple console.log() statement in our function, but in a little while that will change.
Now, let’s go to our AuthState.js and write the function for logout. This function simply clears the AsyncStorage where the user token is saved.
In the above code block we imported thee useContext hook from ReactJS, then we imported our AuthContext. Next, we destructured the userSignout function from our AuthContext and this userSignout() function is called in our onLogout() function.
Now whenever our logout button is clicked, the user token in our AsyncStorage is cleared.
Voila! our entire process is finished.
Here’s what happens when you press the back button after you’re logged in:
Here’s what happens when you press the back button after logging out:
Here are some different behaviors we notice when using this pattern in our navigation stack switching:
You’ll notice that there was nowhere we needed to make use of navigation.navigate() or navigation.push()
to go to another route after login. Once our state is updated with the
user token, the navigation stack rendered is automatically changed.
Pressing the back button on your device after login is successful
cannot take you back to the login page, instead, it closes the app
entirely. This behavior is important because you don’t want the user to
be able to return back to the login page except they log out of the app.
The same thing applies to logging out — once the user logs out, they
cannot use the back button to return to the HomeScreen screen, but instead, the app closes.
In many Apps, authentication is one of the most important parts
because it confirms that the person trying to gain access to protected
content has the right to access the information. Learning how to do it
right is an important step in building a great, intuitive, and easy to
use/navigate the application.
Building on top of this code, here are a few things you might consider adding:
Firebase authentication for integrating authentication with Gmail,
Github, Facebook, Twitter, or your custom interface. Check out React Native Firebase.