[codorial] proof read changes
This commit is contained in:
parent
040f3333c7
commit
ec0dbb267f
|
@ -4,7 +4,7 @@ React Navigation has gone through many cycles of navigation implementations and
|
||||||
A current "go to" navigation library is called [react-navigation](https://reactnavigation.org/). It's pure JavaScript implementation
|
A current "go to" navigation library is called [react-navigation](https://reactnavigation.org/). It's pure JavaScript implementation
|
||||||
which performs well and provides a solid foundation for navigation on both Android and iOS.
|
which performs well and provides a solid foundation for navigation on both Android and iOS.
|
||||||
|
|
||||||
Authentication typically requires 3 screens; Login, Register & Forgot Password.
|
In this step we'll be focusing on adding a Login & Register screen to our app.
|
||||||
|
|
||||||
## Installation
|
## Installation
|
||||||
|
|
||||||
|
@ -103,7 +103,7 @@ library provides a simple, React like API to style and control your app.
|
||||||
For this example we're going to add a title to our screen and liven up the colors - there's loads more you can do with `react-navigation` though,
|
For this example we're going to add a title to our screen and liven up the colors - there's loads more you can do with `react-navigation` though,
|
||||||
just check out their in-depth [documentation](https://reactnavigation.org/docs/getting-started.html).
|
just check out their in-depth [documentation](https://reactnavigation.org/docs/getting-started.html).
|
||||||
|
|
||||||
Lets go ahead and style the screen, using a class static `navigationOptions` object which lets `react-navigation` access our screen component:
|
Lets go ahead and style the screen, using a class static `navigationOptions` object which lets `react-navigation` access our screen component styling:
|
||||||
|
|
||||||
```jsx
|
```jsx
|
||||||
// src/screens/unauthenticated/Login.js
|
// src/screens/unauthenticated/Login.js
|
||||||
|
|
|
@ -9,13 +9,13 @@ The Firebase API allows us to call `signInAndRetrieveDataWithCredential` with a
|
||||||
|
|
||||||
## Installing `react-native-fbsdk`
|
## Installing `react-native-fbsdk`
|
||||||
|
|
||||||
Luckily as Facebook own React Native, they provide a handy wrapper around the own SDK to integrate with React Native, called [`react-native-fbsdk`](https://github.com/facebook/react-native-fbsdk).
|
Luckily as Facebook own React Native, they provide a handy wrapper around their own SDK to integrate with React Native, called [`react-native-fbsdk`](https://github.com/facebook/react-native-fbsdk).
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
npm install --save react-native-fbsdk
|
npm install --save react-native-fbsdk
|
||||||
```
|
```
|
||||||
|
|
||||||
To save explaining how to install this library, refer to their [documentation[(https://developers.facebook.com/docs/react-native) on how to
|
To save explaining how to install this library, refer to their [documentation](https://developers.facebook.com/docs/react-native) on how to
|
||||||
install the library into your React Native project on both Android & iOS.
|
install the library into your React Native project on both Android & iOS.
|
||||||
|
|
||||||
## Creating a credential
|
## Creating a credential
|
||||||
|
|
|
@ -1,18 +1,18 @@
|
||||||
# Getting Started
|
# Getting Started
|
||||||
|
|
||||||
Welcome to the 'Authentication with Firebase' Codorial using the [react-native-firebase](https://rnfirebase.io) library.
|
Welcome to the 'Authentication with Firebase' Codorial, using [React Native](http://facebook.github.io/react-native/) and [react-native-firebase](https://rnfirebase.io).
|
||||||
The various steps of the Codorial will cover how to setup your application to require both email/password login and social login using Facebook,
|
Over the Codorial we'll cover how to setup your application to require both email/password login and social login using Facebook,
|
||||||
to handling the users authenticated state using the popular [redux](https://redux.js.org/introduction) library whilst also considering integrate routing
|
to handling the users authenticated state using the popular [redux](https://redux.js.org/introduction) library whilst also integrating routing
|
||||||
using [react-navigation](https://reactnavigation.org/).
|
using [react-navigation](https://reactnavigation.org/).
|
||||||
|
|
||||||
## Prerequisites
|
## Prerequisites
|
||||||
|
|
||||||
This Codorial assumes you know the basics of the following topics:
|
This Codorial assumes you know the basics of the following topics:
|
||||||
|
|
||||||
|
- React JS.
|
||||||
- ES6 JavaScript.
|
- ES6 JavaScript.
|
||||||
- Starting your app using an emulator on Android/iOS.
|
- Starting an app using an emulator on Android/iOS.
|
||||||
- Understand how to setup a new Firebase project.
|
- Understand how to setup a new Firebase project.
|
||||||
- Debugging with React Native.
|
|
||||||
- Managing your project using Android Stuido and/or XCode.
|
- Managing your project using Android Stuido and/or XCode.
|
||||||
- Installation of the [react-native-firebase](https://rnfirebase.io) library (see "Creating a base project" below).
|
- Installation of the [react-native-firebase](https://rnfirebase.io) library (see "Creating a base project" below).
|
||||||
|
|
||||||
|
|
|
@ -52,7 +52,7 @@ export default App;
|
||||||
|
|
||||||
## Updating Redux with the user state
|
## Updating Redux with the user state
|
||||||
|
|
||||||
Rather than passing our `user` into component `state`, we're going to add into into Redux instead. Firebase does provide direct access to the user
|
Rather than passing our `user` into component `state`, we're going to add it into into Redux instead. Firebase does provide direct access to the user
|
||||||
via `firebase.auth().currentUser`, however as our app complexity grows we may want to integrate parts of the users data (for example the `uid`) into
|
via `firebase.auth().currentUser`, however as our app complexity grows we may want to integrate parts of the users data (for example the `uid`) into
|
||||||
other parts of our Redux store. By storing the user in Redux, it is guaranteed that the user details will keep in-sync throughout our Redux store.
|
other parts of our Redux store. By storing the user in Redux, it is guaranteed that the user details will keep in-sync throughout our Redux store.
|
||||||
|
|
||||||
|
@ -77,8 +77,8 @@ export function userStateChanged(user) {
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
To dispatch this action we need to again make use of `react-redux`. As our `App.js` has been provided the Redux store within `index.js` we can
|
To dispatch this action we need to again make use of `react-redux`. As our `App.js` has been provided the Redux store via the `Provider`
|
||||||
use a [higher order component (HOC)](https://reactjs.org/docs/higher-order-components.html) called `connect` to provide the component with access to Redux:
|
component within `index.js`, we can use a [higher order component (HOC)](https://reactjs.org/docs/higher-order-components.html) called `connect` to provide the component with access to Redux:
|
||||||
|
|
||||||
```jsx
|
```jsx
|
||||||
// src/App.js
|
// src/App.js
|
||||||
|
@ -90,7 +90,7 @@ import { connect } from 'react-redux';
|
||||||
export default connect()(App);
|
export default connect()(App);
|
||||||
```
|
```
|
||||||
|
|
||||||
The `connect` HOC clones the given component with a function prop called `dispatch`. The function then takes an action, which when called 'dispatches'
|
The `connect` HOC clones the given component with a function prop called `dispatch`. The `dispatch` function then takes an action, which when called 'dispatches'
|
||||||
it to Redux. Lets jump back into our `App.js` and dispatch our action when `onAuthStateChanged` is triggered:
|
it to Redux. Lets jump back into our `App.js` and dispatch our action when `onAuthStateChanged` is triggered:
|
||||||
|
|
||||||
```jsx
|
```jsx
|
||||||
|
@ -102,7 +102,6 @@ import { userStateChanged } from './actions';
|
||||||
...
|
...
|
||||||
|
|
||||||
componentDidMount() {
|
componentDidMount() {
|
||||||
// Listen for user auth state changes
|
|
||||||
firebase.auth().onAuthStateChanged((user) => {
|
firebase.auth().onAuthStateChanged((user) => {
|
||||||
|
|
||||||
// dispatch the imported action using the dispatch prop:
|
// dispatch the imported action using the dispatch prop:
|
||||||
|
@ -158,7 +157,7 @@ previous state with a new one.
|
||||||
|
|
||||||
### Subscribing to Redux state
|
### Subscribing to Redux state
|
||||||
|
|
||||||
Now our user data is updating the store whenever it changes, we can subscribe to specific parts of the data which we need in out React
|
Now our action is updating the store whenever it's dispatched, we can subscribe to specific parts of the data which we need in our React
|
||||||
components. The power of using `react-redux` is that it allows us to subscribe to data within our store and update the component whenever that
|
components. The power of using `react-redux` is that it allows us to subscribe to data within our store and update the component whenever that
|
||||||
data changes - we do this via a function known as `mapStateToProps`. This function is passed as the first argument of our `connect` HOC and gets
|
data changes - we do this via a function known as `mapStateToProps`. This function is passed as the first argument of our `connect` HOC and gets
|
||||||
given the current Redux state. It returns an object, which is cloned as props into our component. Here's how it works:
|
given the current Redux state. It returns an object, which is cloned as props into our component. Here's how it works:
|
||||||
|
@ -174,7 +173,7 @@ export default connect(mapStateToProps)(App);
|
||||||
```
|
```
|
||||||
|
|
||||||
With this code, our `App` component will receive a prop called `isUserAuthenticated`, which in our case will be a `true` or `false` value based on
|
With this code, our `App` component will receive a prop called `isUserAuthenticated`, which in our case will be a `true` or `false` value based on
|
||||||
whether the `state.user` object exists or not. Every time Redux state changes, this logic is run. What's cool is that if the result of any
|
whether the `state.user` object exists or not. Every time Redux state changes, this logic is run. What's handy is that if the result of any
|
||||||
prop has changed, the component will be updated with the new data. If none of the props-to-be have changed, the component doesn't update.
|
prop has changed, the component will be updated with the new data. If none of the props-to-be have changed, the component doesn't update.
|
||||||
|
|
||||||
> Keep in mind that if you return a complex `Array` or `object`, `react-redux` will only shallow compare them. Even if your state does not change
|
> Keep in mind that if you return a complex `Array` or `object`, `react-redux` will only shallow compare them. Even if your state does not change
|
||||||
|
@ -182,7 +181,7 @@ the component will still be re-rendered with the same data which can cause perfo
|
||||||
to break components out to only subscribe to specific parts of primitive state (such as `strings`, `booleans` etc).
|
to break components out to only subscribe to specific parts of primitive state (such as `strings`, `booleans` etc).
|
||||||
|
|
||||||
As our `App` component contains our routes, any change in the `isUserAuthenticated` value will cause the entire app to re-render - which in this case
|
As our `App` component contains our routes, any change in the `isUserAuthenticated` value will cause the entire app to re-render - which in this case
|
||||||
is fine as we're conditionally changing navigation stacks. Lets implement that:
|
is fine as we're conditionally changing navigation stacks. Lets implement that logic:
|
||||||
|
|
||||||
```jsx
|
```jsx
|
||||||
// src/App.js
|
// src/App.js
|
||||||
|
@ -192,6 +191,7 @@ import firebase from 'react-native-firebase';
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
|
|
||||||
import UnauthenticatedStack from './screens/unauthenticated';
|
import UnauthenticatedStack from './screens/unauthenticated';
|
||||||
|
import AuthenticatedStack from './screens/authenticated';
|
||||||
import { userStateChanged } from './actions';
|
import { userStateChanged } from './actions';
|
||||||
|
|
||||||
class App extends Component {
|
class App extends Component {
|
||||||
|
@ -204,7 +204,6 @@ class App extends Component {
|
||||||
}
|
}
|
||||||
|
|
||||||
componentDidMount() {
|
componentDidMount() {
|
||||||
// Listen for user auth state changes
|
|
||||||
firebase.auth().onAuthStateChanged((user) => {
|
firebase.auth().onAuthStateChanged((user) => {
|
||||||
|
|
||||||
this.props.dispatch(userStateChanged(user));
|
this.props.dispatch(userStateChanged(user));
|
||||||
|
|
|
@ -4,10 +4,10 @@ Redux has become somewhat of a buzz word in the React community, and is generall
|
||||||
won't go into details on what it is as their own [documentation](https://redux.js.org/introduction/motivation) does a wonderful job at explaining
|
won't go into details on what it is as their own [documentation](https://redux.js.org/introduction/motivation) does a wonderful job at explaining
|
||||||
what it's for and why to use it.
|
what it's for and why to use it.
|
||||||
|
|
||||||
*TLDR* Redux provides your app with a single "state" (data), which can be accessed by any component. You can subscribe to this data to cause
|
*TLDR;* Redux provides your app with a single "state" (data), which can be accessed by any component. You can subscribe to this data to cause
|
||||||
a component update whenever something changes, even if it's deeply nested.
|
a component update whenever something changes, even if it's deeply nested.
|
||||||
|
|
||||||
Although the end product of this Codorial certain doesn't require Redux to function, as your app grows in complexity Redux becomes more and
|
Although the end product of this Codorial certainly doesn't require Redux to function, as your app grows in complexity Redux becomes more and
|
||||||
more important to manage your data.
|
more important to manage your data.
|
||||||
|
|
||||||
## Installing Redux
|
## Installing Redux
|
||||||
|
@ -33,9 +33,11 @@ function reducer(state = {}, action) {
|
||||||
export default createStore(reducer);
|
export default createStore(reducer);
|
||||||
```
|
```
|
||||||
|
|
||||||
As default state is `null`, we set the default to be an empty `object` so we can access it later on.
|
By default state is `null`, however we're setting it to an empty `object` (`state = {}`) so we can attempt to access
|
||||||
|
shallow nested properties even if they don't exist.
|
||||||
|
|
||||||
> You may want to consider installing the [redux-logger](https://github.com/evgenyrodionov/redux-logger) library.
|
> You may want to consider installing the [redux-logger](https://github.com/evgenyrodionov/redux-logger) library to improve
|
||||||
|
your Redux experience.
|
||||||
|
|
||||||
### Reducer
|
### Reducer
|
||||||
|
|
||||||
|
|
|
@ -1,12 +1,13 @@
|
||||||
# Project Structure
|
# Project Structure
|
||||||
|
|
||||||
Although it may seem trivial, having a good initial project structure ensures you code will be clean and reusable. The following step gives
|
Although it may seem trivial, having a good initial project structure ensures your code will be clean and reusable.
|
||||||
an opinionated guide to how this might look, which will work across both Android & iOS.
|
The following step gives an opinionated guide to how this might look, which will work across both Android & iOS.
|
||||||
|
|
||||||
## Entry file
|
## Entry file
|
||||||
|
|
||||||
Every fresh React Native project contains two key files, an `index.android.js` & a `index.ios.js` files which currently individually render a simple React component
|
Every fresh React Native project a key file, an `index.js`, which currently renders a simple React component
|
||||||
with basic styling. Rather than having two separate files, we're going to create a single file so both Android & iOS use it.
|
with basic styling. Rather than keeping our business logic within this file, we're going to keep it contained in it's own
|
||||||
|
directory.
|
||||||
|
|
||||||
We'll achieve this by creating a `src` directory where our own code for the app will live. Create the directory with an `index.js` file, so your
|
We'll achieve this by creating a `src` directory where our own code for the app will live. Create the directory with an `index.js` file, so your
|
||||||
project structure resembles the following:
|
project structure resembles the following:
|
||||||
|
|
|
@ -8,12 +8,12 @@ Luckily [react-native-firebase](https://rnfirebase.io) follows the Firebase web
|
||||||
|
|
||||||
## Enabling authentication
|
## Enabling authentication
|
||||||
|
|
||||||
Before we make a start, we need to tell Firebase that we plan on using authentication. We need to also enable a couple of the many login providers
|
We need to tell Firebase that we plan on using authentication and also enable a couple of the many login providers
|
||||||
which Firebase supports. Head over to the [Firebase console](https://console.firebase.google.com/u/0/) and select the project you're using.
|
which Firebase supports. Head over to the [Firebase console](https://console.firebase.google.com/u/0/) and select the project you're using.
|
||||||
|
|
||||||
Find the Authentication section and you'll be prompted with a number of options. To get started, we want to select the "SIGN-IN METHOD" tab.
|
Find the Authentication section and you'll be prompted with a number of options. To get started, we want to select the "SIGN-IN METHOD" tab.
|
||||||
|
|
||||||
You'll see we have a number of options here, however for purposes of this Codorial we'll be using "Email/Password" and "Facebook" as our providers.
|
You'll see we have a number of options here, however for the purposes of this Codorial we'll be using "Email/Password" and "Facebook" as our providers.
|
||||||
Go ahead and enable these:
|
Go ahead and enable these:
|
||||||
|
|
||||||
![Enabled Providers](assets/auth-providers.jpg)
|
![Enabled Providers](assets/auth-providers.jpg)
|
||||||
|
@ -38,7 +38,7 @@ The callback for the `onAuthStateChanged` method returns a single parameter, com
|
||||||
The concept here is simple;
|
The concept here is simple;
|
||||||
|
|
||||||
- the method is first called once Firebase responds, then any time user state changes thereafter.
|
- the method is first called once Firebase responds, then any time user state changes thereafter.
|
||||||
- if a user is "signed in", our parameter will be a `class`, containing all sorts of information we know about the user,
|
- if a user is "signed in", our parameter will be a [`User`](https://firebase.google.com/docs/reference/js/firebase.User) `class`, containing all sorts of information we know about the user,
|
||||||
from their e-mail address to any social provider IDs they may have signed in through.
|
from their e-mail address to any social provider IDs they may have signed in through.
|
||||||
- if the user signed out, the parameter will be `null` value.
|
- if the user signed out, the parameter will be `null` value.
|
||||||
|
|
||||||
|
@ -68,7 +68,7 @@ firebase.auth().createUserAndRetrieveDataWithEmailAndPassword('jim.bob@gmail.com
|
||||||
});
|
});
|
||||||
```
|
```
|
||||||
|
|
||||||
What's great about this is we don't need to know about the user within the `then`, as any `onAuthStateChanged` listener would get triggered with our new
|
What's great about this is we don't need to know about the user within the `.then`, as any `onAuthStateChanged` listener would get triggered with our new
|
||||||
users details - how awesome is that.
|
users details - how awesome is that.
|
||||||
|
|
||||||
## Signing into an existing account
|
## Signing into an existing account
|
||||||
|
@ -157,7 +157,7 @@ When subscribing to a new listener, such as `onAuthStateChanged`, a new referenc
|
||||||
React environment. If a component within your app mounts and subscribes, the method will still trigger even if your component unmounted.
|
React environment. If a component within your app mounts and subscribes, the method will still trigger even if your component unmounted.
|
||||||
If this happens and you're updating state, you'll get a yellow box warning.
|
If this happens and you're updating state, you'll get a yellow box warning.
|
||||||
|
|
||||||
To get around this, Firebase returns an unsubscribe function to every subscriber method, which when calls removes the subscription.
|
To get around this, Firebase returns an unsubscribe function to every subscriber method, which when calls removes the subscription from memory.
|
||||||
This can be easily implemented using React lifecycle methods and class properties:
|
This can be easily implemented using React lifecycle methods and class properties:
|
||||||
|
|
||||||
```jsx
|
```jsx
|
||||||
|
|
Loading…
Reference in New Issue