[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
|
||||
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
|
||||
|
||||
|
@ -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,
|
||||
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
|
||||
// src/screens/unauthenticated/Login.js
|
||||
|
|
|
@ -9,13 +9,13 @@ The Firebase API allows us to call `signInAndRetrieveDataWithCredential` with a
|
|||
|
||||
## 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
|
||||
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.
|
||||
|
||||
## Creating a credential
|
||||
|
|
|
@ -1,18 +1,18 @@
|
|||
# Getting Started
|
||||
|
||||
Welcome to the 'Authentication with Firebase' Codorial using the [react-native-firebase](https://rnfirebase.io) library.
|
||||
The various steps of the Codorial will 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
|
||||
Welcome to the 'Authentication with Firebase' Codorial, using [React Native](http://facebook.github.io/react-native/) and [react-native-firebase](https://rnfirebase.io).
|
||||
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 integrating routing
|
||||
using [react-navigation](https://reactnavigation.org/).
|
||||
|
||||
## Prerequisites
|
||||
|
||||
This Codorial assumes you know the basics of the following topics:
|
||||
|
||||
- React JS.
|
||||
- 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.
|
||||
- Debugging with React Native.
|
||||
- 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).
|
||||
|
||||
|
|
|
@ -52,7 +52,7 @@ export default App;
|
|||
|
||||
## 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
|
||||
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
|
||||
use a [higher order component (HOC)](https://reactjs.org/docs/higher-order-components.html) called `connect` to provide the component with access to Redux:
|
||||
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`
|
||||
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
|
||||
// src/App.js
|
||||
|
@ -90,7 +90,7 @@ import { connect } from 'react-redux';
|
|||
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:
|
||||
|
||||
```jsx
|
||||
|
@ -102,7 +102,6 @@ import { userStateChanged } from './actions';
|
|||
...
|
||||
|
||||
componentDidMount() {
|
||||
// Listen for user auth state changes
|
||||
firebase.auth().onAuthStateChanged((user) => {
|
||||
|
||||
// dispatch the imported action using the dispatch prop:
|
||||
|
@ -158,7 +157,7 @@ previous state with a new one.
|
|||
|
||||
### 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
|
||||
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:
|
||||
|
@ -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
|
||||
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.
|
||||
|
||||
> 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).
|
||||
|
||||
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
|
||||
// src/App.js
|
||||
|
@ -192,6 +191,7 @@ import firebase from 'react-native-firebase';
|
|||
import { connect } from 'react-redux';
|
||||
|
||||
import UnauthenticatedStack from './screens/unauthenticated';
|
||||
import AuthenticatedStack from './screens/authenticated';
|
||||
import { userStateChanged } from './actions';
|
||||
|
||||
class App extends Component {
|
||||
|
@ -204,7 +204,6 @@ class App extends Component {
|
|||
}
|
||||
|
||||
componentDidMount() {
|
||||
// Listen for user auth state changes
|
||||
firebase.auth().onAuthStateChanged((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
|
||||
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.
|
||||
|
||||
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.
|
||||
|
||||
## Installing Redux
|
||||
|
@ -33,9 +33,11 @@ function reducer(state = {}, action) {
|
|||
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
|
||||
|
||||
|
|
|
@ -1,12 +1,13 @@
|
|||
# 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
|
||||
an opinionated guide to how this might look, which will work across both Android & iOS.
|
||||
Although it may seem trivial, having a good initial project structure ensures your code will be clean and reusable.
|
||||
The following step gives an opinionated guide to how this might look, which will work across both Android & iOS.
|
||||
|
||||
## 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
|
||||
with basic styling. Rather than having two separate files, we're going to create a single file so both Android & iOS use it.
|
||||
Every fresh React Native project a key file, an `index.js`, which currently renders a simple React component
|
||||
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
|
||||
project structure resembles the following:
|
||||
|
|
|
@ -8,12 +8,12 @@ Luckily [react-native-firebase](https://rnfirebase.io) follows the Firebase web
|
|||
|
||||
## 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.
|
||||
|
||||
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:
|
||||
|
||||
![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 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.
|
||||
- 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.
|
||||
|
||||
## 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.
|
||||
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:
|
||||
|
||||
```jsx
|
||||
|
|
Loading…
Reference in New Issue