Table Of Contents

Coding Notes

React For Beginners Notes

February 04, 2019


React For Beginners Course

demo: View Live Demo

GitHub: https://github.com/anjagusev/Catch-Of-The-Day local: repos/React-For-Beginners-Start-Files

React-For-Beginners-Starter-Files/catch-of-the-day at master · wesbos/React-For-Beginners-Starter-Files · GitHub

NTS: Found solution: removed package-lock.json and run rm -rf node_modules && npm i.


1 - Introduction, Tooling and Editor Setup

You need Node.js installed for tooling to develop locally. Install React dev tools. Make sure you are using the Javascript(babel) highlighter if you are using sublime text.

We will be working out of /catch-of-the-day directory which has only a /src and /public directory with a package.json file and a few more files.

TIP: If you have terminal open, and in finger you have your directory, you can drop it into terminal to get the path.

Packages.json - Contains dev dependencies needed to locally run our application . React-scripts does all of the compiling and transpiling under the hood. It takes the complexity out of setting up the dev environment and sweeps it under the rug. If we want access, we will eject which will give us the full control.

In the catch of day directory run npm install

To start run npm start

If you want to test it on your phone, if you are on the same wifi you can use the network address.

39D48E76 5FCA 477C B8E1 5EDE87E925E2

Go to /src/index.js and add alert(‘hey') and see if it shows up.


2 - Thinking and Understanding React Components

Everything in React is a component, they are reusable pieces of code. Use React Dev tools to explore.


3 - Creating our First Component

When we created the alert(‘hey”) web pack bundles everything in the index.js file into this static/js/bundle.js

CC76F151 A102 4943 AEA0 4ED213B5B493

The /public/index.html file is the entry point where we will mount React.

In the /src/index.js you actually mount React wit something like

2F15A0DF 7D10 4160 8DAA A756B7B1B802

Or

5952F03E 0813 476D 9023 56F65862F875

In the /components/ directory create a file called StorePicker.js and move the store picker component to there.

import React from “react”;


class StorePicker extends React.Component {

  render() {
    return <p>Hello!</p>
  }
}
export default StorePicker;

Now in src/index.js we import it and out it like so:

import React from "react"
import { render } from "react-dom"
import StorePicker from "./components/StorePicker"

render(<StorePicker />, document.querySelector("#main"))

4 - Writing HTML with JSX

You can do

import React from ‘react’;
class StorePicker extends React.Component{}

But you can also just import part of React like

import { Component } from ‘react’;
class StorePicker extends Component {}

You need to use className instead of class.

Render determines which Dom elements we render out to the page

Javascript way of writing HTML:

React uses JSX instead to write Html in react components. An alternative to JSX is React.createElement(‘p’, { className: ‘hey’ }, React.createElement());

If you have multi-lined html you need to wrap it around parenthesis

  return (
       <form className=“store-selector”>
        <h2>Please Enter A Store</h2>
       </form>
       )

You cannot have sibling elements You can only return one element from a return statement

If you are using flex box or css grid where you need to return 6 or 7 children with no wrapper, you can wrap them in a <React.Fragment> tag.

<React.Fragment />

This is new in React.16.2.

Commenting in JSX -use curly brackets {/* test */}

-Comments cannot be sibling, must be children


5 - Loading CSS into our React Applications

Many different approaches to CSS with React. You may already have existing css build process. What you can do is open the index.html mounting point and just load the css via a link tag as usual like so:

EA5B7F69 FCFE 4770 99E9 CDDACF311D68

Componentized CSS -import css that only applies to that component -tightly coupled css and the component

You can also import the css directly into the src/index.js file.

40DE18D1 8ABF 4F1F 8AD1 F3162F826AAB

Webpack will know this is a CSS file so it will load the css, stick it in a style tag, and then anytime we make a change it will hot reload.

When we are deploying, we will kick out a separate .css file.

We are going to talk about compiling from SASS in the animation video.


6 - Creating out Application Layout with Components

We are going to create an App component which will be the parent component.

All the other components will be sibling components which will allow us to share data.

D5254432 78EF 406D 82F2 2525F7A41B26

FA77D371 11B5 441E B423 76FDC09D11B4


7 - Passing Dynamic Data with Props

Props - the way we get data into a component

State -where the data lives

State is where the data lives and props is how it gets to where it needs to go.

In App.js (container app which has

component), modify the Header tag to include a prop. Then in Header.js, replace the static text with this.props.propname.

E86BCA43 FE87 485F AD93 290590721FE9

5CB8C2EB 1AB8 4D0E 8FB1 1682BF9CE27B

-this.props.tagline … this refers to component instance

To pass anything other than a string as a prop you use {}

If in React dev tools you click on a component, you can then reference it in the console using $r and it will show you B5F868AD 18B1 43C1 A3BB DE8E2A1DF94A

BC512983 1F1E 4B3F BF0D 04822B8CBC0A

NON REACT: If you select an item on the elements dev tools, and then go to the console and type $0, it will show that element.


8 - Stateless Functional Components

If there is no dynamic data, there is no need for it to be an entire component, it’s essentially just a render function which renders out some HTML. (If only render method and prop types, it is a stateless functional component).

Stateless functional component does not have “this”, instead pass props as a parameter to the function and then instead of {this.props.tagline} you would use {props.tagline}

function Header(props){}
can be rewritten as an arrow function like so:
const Header = (props) => {}

Implicit return: const Header = props => ()

rather than const Header = props => { return()};

If more than two params you can do const Header = (props, i) => (); if only one param, do not need to include ()

Another way to pass props:

const Header = ({ tagline, age }) => ()
then you can just reference { tagline } in c ode.

9 - React Router Step

Routing is not baked into React

<Switch/> the way the switch tag works is that it’s going to try the first route, then the second route and then fallback to not found

<Route exact path="/" component={StorePicker} />

^ When the path exactly matches “/“ load the component storepicker

If the path is equal to forward slash store forward slash anything, /store/:storeId .. works as a catchall for the store name

How including the routing component looks in React Dev Tools.. BE251599 4CB8 4F99 955E A890822983C5


10 - Helper Functions

Just plain javascript, not React.

You can export functions from Helper.js. import { getFunName } from '../helpers";

difference between value and defaultValue in React. If you put value=“hello” on an input, react will yell at you. Values of inputs have to be attached to state.

For default text in a React Input use the attribute defaultValue.

To use exported method you can do as follows:

<input type="text" required placeholder="Store Name" defaultValue={getFunName()}/>

11 - Events

Exactly the same as vanilla js except React wraps your events in a Synthetic Event which ensures the events work cross browser and cross device.

Events are done inline in React.

<button onClick={this.handleClick} > Click me! </button>

26EDF986 9494 465A AA73 F98A6C2EAF4A 3495C96B D885 4C86 BA25 05598B225FD5

Golden rule in React: don’t touch the DOM!

A ref allows us to actually reference an actual Dom node on the page

There are a few ways to add refs

ref="myInput" DEPRECATED

ref={(myInput) => this.myInput = myINput} confusing but works

You can create a ref by doing this…

class StorePicker extends React.Component{
myInput = React.createRef();

render(){
return(....
<input
ref={this.myInput}
...
}

If above the render method you have a function like

goToStore(event){
console.log(this.myInput);
console.log(this);
}

You will get an error, this is undefined. If you use it within the render method, this works.

This is because of how binding works in React.

React has built in lifecycle events and methods like render();

componentDidMount you can use the “this” keyword inside of it because its a built in method that comes with React, and they are in the React.Component parent. We make our own component that extends that (like StorePicker) and any methods that we then add ontop are not bound by default.

It’s hard to reference the component within one of it’s own methods which is a problem.

Solution: bind our own methods as well

Because es6 classes are new, no standard way to do that however there is a proposal on how to do it with funky syntax

Constructor

You would bind them using a constructor() method, method that runs before store picker component is created .

in constructor you must call super(); Super runs the component that we are extending first. (React.Component)

Next inside the constructor you bind all the methods.

0EA59490 8F69 44D7 8062 0DBC8A285A84

What that does is it overwrites the method on it, and it will attach a binding to, (it will reference “this” inside of the goToStore within the store picker instance.

Instead of using the constructor, you can declare a property which is set to an arrow function.

67FB5F21 96F3 428B A6A7 EDCC724E6ED5

goToStore is a property on the component (just like myInput is a property of the component). Then we set it to an arrow function, which will allow us to bind the value of this to the store picker component.

With an arrow function you can access {this} without binding in the constructor.

If you need to access “this” within a custom method you must use the arrow function syntax or do the whole constructor song and dance.


12 - Handling Events

Step 3 Change page to /store/whatever-name

We don’t actually want to refresh page, just change the url with “push state”.

It allows us to change the url without having to refresh the page or lose anything that we have in memory.

No way to pass something from a high level to a low level without passing it as props in react, so if the component was a few layers deep it would be difficult.

Since store picker is a child of the router, we have access to all the methods we need.

myInput = React.createRef()
goToStore = event => {
  //1. Stop form from submitting
  event.preventDefault()
  //2. get the text from that input
  const storeName = this.myInput.current.value
  //3. Change the page to /store/whatever-the-store-name
  this.props.history.push(`/store/${storeName}`)
}

The reason it is so fast is that we are no reloading anything or loading other pages. The router instead if say oh, this no longer matches, but this route does, so load the associated component.


13 - Understanding State

Is an object that lives inside of a component that stores all of the data /holds data that itself and it’s children may need.

React, reacts to changes in states and re-renders

Add Fish Form

We need to turn the inputs into an actual fish object that has the values and properties on it.

To do that we add onSubmit to the form.

There are two ways we can pull the values out of the inputs. One is refs, giving a ref to every single input. Or we could listen to a keyup event, and mirror the data to state.

-to each input, add ref={this.statusRef} and then in function above capture those ref values and set them to a const, like so:

2702994C E7D3 4F21 B270 1F96A6B11E1F

Now we have the fish, but how do we get it into state, and also where does state live?

It is often the case where you have a parent state on one of the components and you pass it to the children.

Right now, the fish const is limited to the add fish form component. We want to give it to inventory, order and menu. There is no way to share that data with those other components, unless that data lives at a higher level .

You cannot pass data up, but you can pass it down.

First you have to set the initial state or empty state. This is what the component looks like when it initially mounts before we have had a chance to add items to our state.

Load a component first with an empty state and then do an Ajax request for example.

How do we get an item into state? You cannot actually update it directly from the AddFishForm because the methods that update state and the actual state always need to live in the exact same component.

How do you get a function that lives in App, down to a lower component? The answer is: props (how does anything get into a component).

EF1D96DC 7BB3 4CE2 9287 D0C4958ED06A

DCA83414 85DA 4B3B A52F 8875372F059E C0D62DD3 54F2 4842 8925 4242E3C975D9

In order to update state, you need to use Reacts set state API or else it’s not going to work.

Two steps to setting state:

  1. Take a copy of the existing state (because you never want to reach into state and actually modify it directly, that is what is called a mutation in JS. const fishes = { ...this.state.fishes}; object spread is a nice clean way to copy Object spread operator An alternative approach is to use the object spread syntax recently added to the JavaScript specification. It lets you use the spread (…) operator to copy enumerable properties from one object to another in a more succinct way.
  2. Add new object to state variable (or add fish to fishes variable) fishes[fish${Date.now()}] = fish;
  3. Set new fishes object to state
this.setState({
fishes:fishes
});

33C04189 A8E5 4BE8 8777 83D537EA1097

HINT: In ES6 if your property and value are the same, you don’t need to do fishes:fishes, you can just do this.setState({fishes});


14 - Loading Data into State onClick

Load Samples Button, we need to add it to the inventory component so when you click a button, it loads the samples

Where do we put that function? In App.js not Inventory.js Why?? Because we have created custom functions which update state, and any custom function which updates state needs to live in the same component where our state lives.

How do you get a function from one component into another? Props! That’s how anything gets anywhere.

In child component that is using the function from another component, you need to use props to access it. this.props.loadSampleFishes


15 - Displaying State with JSX

JSX doesn’t have conditionals or loops of ifs, so you have to use plain javascript for that.

State is an object and you cannot map over an object, a map is for an array.

When you use {} in JSX it’s telling JSX that it’s JS

{Object.keys(this.state.fishes)} Object.keys() - JavaScript | MDN It will loop over fishes and grab the keys for each object, which we can use to loop over every single fish we have. 1378FC33 98E1 4DEF BDB0 37DCB0C17016

ERROR: index.js:1446 Warning: Each child in an array or iterator should have a unique “key” prop. REASON: each component does not have a unique identifier, which React needs to be able to update instance. 261BC35A 6652 4BA5 99D0 4FFB8CD3EAE4 SOLUTION: Give property called key and give a key of anything that is unique

In a component, if you don’t want to keep typing out this.props you can assign the props to variables right underneath the render() method.

ES6 Destructuring.

Instead of

    const image = this.props.details.image;
    const name = this.props.details.name;

You can do const {image, name} = this.props.details;


16 - Updating Order State

8D979EAC F5C6 4C98 8715 3BBB6DD0ECF9 This code will check if order.fish1 exists, if it does it will increment it by 1 if not it will return 1

There is a way to test a function without a click event. In Chrome, go to React tools and find App.js or state component. Then in console you can reference it using $r

You can then use $r to call the function like so: 8E793BA5 FAD4 4CDD 89AA 3D98AF456760

And then in React tools, can you look at the App component, and the state, and the change should be reflected there

Add to order needs to be clicked inside of the fish, so in order to expose the functionality we need to pass it as props.

If you need access to the key, you have to pass it to props as something other then key, such as: 64B4CB2C CA48 4EA6 983A CD40B02B69B2

How to Handle Add to Order Click on Button

In Fish, we can do <button onClick={this.handleClick}/>

And then at top above render() the code would be:

handleClick = () =>{
this.props.addToOrder(this.props.index);
}

Javascript to display conditional text:

{isAvailable? "Add to Order"? "Sold out"}

Javascript to reset a form:

event.currentTarget.reset();


17 - Displaying Order State With JSX

Order right now doesn’t have any information. In order to pass it information, we need to pass it props. We need to pass it at least 2 props: order, and fishes. Both of those props come from state.

Object spread in React … <Order {…this.state } /> That will spread everything from state into Order.

Avoid passing entire state, because components are modular and may be reused. What if you add to state later?

Javascript 30.com, Array Cardio Day 1 and 4 Map, filter, reduce

As soon as you have too much code in your render function, that probably means you are doing too much in one component and you can probably shell of some of that complexity to a separate component.. but sometimes it doesn’t warrant an entire new component

Wesbos likes to do is make separate render functions inside of a single component.

 import React from “react”;
import { formatPrice } from “../helpers”;
class Order extends React.Component {
  render() {
    const orderIds = Object.keys(this.props.order);
    const total = orderIds.reduce((prevTotal, key) => {
      const fish = this.props.fishes[key];
      const count = this.props.order[key];
      const isAvailable = fish && fish.status === “available”;
      if (isAvailable) {
        return prevTotal + count * fish.price;
      }
      return prevTotal;
    }, 0);
    return (
      <div className=“order-wrap”>
        <h2>Order</h2>
        <ul>
          {orderIds.map(key => (
            <li>{key}</li>
          ))}
        </ul>
        <div className=“total”>
          <strong>{formatPrice(total)}</strong>
        </div>
      </div>
    );
  }
}

export default Order;

Instead he will break up render() like so:

class Order extends React.Component {
  renderOrder = key => {
    return <li>{key}</li>;
  };
  render() {
    const orderIds = Object.keys(this.props.order);
    const total = orderIds.reduce((prevTotal, key) => {
      const fish = this.props.fishes[key];
      const count = this.props.order[key];
      const isAvailable = fish && fish.status === “available”;
      if (isAvailable) {
        return prevTotal + count * fish.price;
      }
      return prevTotal;
    }, 0);
    return (
      <div className=“order-wrap”>
        <h2>Order</h2>
        <ul>{orderIds.map(this.renderOrder)}</ul>
        <div className=“total”>
          <strong>{formatPrice(total)}</strong>
        </div>
      </div>
    );
  }
}

Before we return list item in renderOrder method, we need to check first if the fish is available.


18 - Persisting our State with Firebase

We want to save to a database so when we come back to it later, that data needs to be available to them.

Go to firebase.google.com and create a new project.

Go to product and in src/ folder, create a new file called base.js and import Rebase which is a package that allows React and firebase to work together to mirror state to the firebase changes.

Also import firebase package from firebase, and we use that for everything that is no mirroring to state.

We turned off authentication temporarily on the database, and then went to project overview -> chose the code option -> copied the values for var config.

We have created our firebase app and rebase bindings, and now we have to export them.

Next we need to go to App.js and mirror our fish state into our firebase. But in order to do that we need to wait until the app component is on the page and then we sync them up.

Lifecycle Methods

componentDidMount - is like a hook into the very first possible second that the application is loaded onto the page.

this.ref is a firebase command

 componentDidMount() {
    const { params } = this.props.match;
    this.ref = base.syncState(`${params.storeId}/fishes`, {
      context: this,
      state: “fishes”
    });
  }

Memory leak is possible if we are always listening to changes, and not unlisteninh.

When component is unmounted, we want to stop listening.

  componentWillUnmount() {
    base.removeBinding(this.ref);
  }

19 - Persisting Order State with localstorage

A different way to persist state without a database but within the browser.

Local storage works with key value storage You can pull that data back into the application.

componentDidUpdate() Is called immediately after updating occurs, and is not called on the initial render. As soon as it’s loaded and as soon as someone modifies their order, we want to update our local storage showing this is exactly what they added to their order.

console.log(wes) = [object Object] JSON.stringify(wes) = {“name”:”wes”}

JSON.parse(localStorageRef) this will switch it back to an object.


20 - Bi-directional Data Flow and Live State Editing

Added component, passed fishes={this.state.fishes} to Inventory component from App.js

Added same inputs as AddFishForm.

We need to pass individual fish down to the EditFishForm using following js:

{Object.keys(this.props.fishes).map(key => (
          <EditFishForm fish={this.props.fishes[key]} />
        ))}

WARNING: index.js:1446 Warning: Each child in an array or iterator should have a unique “key” prop. FIX: Add key= prop to EditFIshForm like so:

<EditFishForm key={key} fish={this.props.fishes[key]} />

WARNING: index.js:1446 Warning: Failed prop type: You provided a value prop to a form field without an onChange handler. This will render a read-only field. If the field should be mutable use defaultValue. Otherwise, set either onChange or readOnly.

React doesn’t like you putting state in an editable area without having a plan to update it. WHY? Because as soon as you put state into a textbox, you have state in two spots. It’s spread across two different areas.

So we add on onChange={} attribute to the inputs in the fish form, like so:

        <input
          type=“text”
          name=“name”
          onChange={this.handleChange}
          value={this.props.fish.name}
        />

Now we need to create an updated fish object and somehow swim upstream from edit fish form to inventory and then to app. We need to get that updated fish back into our state.

What if you want to change the price? It doesn’t work! (It updates name instead) Why? It doesn’t know which property to update

console.log(event.currentTarget.name) tells us which property name was updated

ES6 Computed Property Names

const updatedFish = {
      …this.props.fish,
      [event.currentTarget.name]: event.currentTarget.value
    };

How do we get updated fish to swim upstream? Go back to where our state is (our app component).
Below AddFish function we add updateFish property (function).

updateFish = (key, updatedFish) => {
    //1. take a copy of the current state
    const fishes = { ...this.state.fishes };
    //2. update that state
    fishes[key] = updatedFish;
    //3. set that to state
    this.setState({ fishes });
  };

Go into Inventory and pass it one step further via props.

In EditFishForm, use that prop in the handleChange function where we call this.props.updateFish(key, updatedFish). Problem is we do not know the key. Although in React dev tools you see the key like so:

699FED88 2D2F 4B98 AC98 9E7E4ECE8A53

You cannot access the key when we are inside of the component so if we need it for whatever reason we have to pass it down ourselves.

In inventory we added:

<EditFishForm
            key={key}
            index={key}
            fish={this.props.fishes[key]}
            updateFish={this.props.updateFish}
          />

21 - Removing Items from State

We will be deleting items from our inventory and from our order.

//takes key of which fish we would like to delete
  deleteFish = key => {
    //1. take a copy of state
    const fishes = { …this.state.fishes };
    //2. update the state
    //if this was an array I would filter using this.state.fishes.filter() and return the new amount of fishes that I want.
    //because it’s an object, we first take a copy of it, and we set the fish that we don’t want to null.
    fishes[key] = null;
    //3. update state
    this.setState({ fishes });
  };

Before hooking it up, we can test it in the console. React dev tools, find App component and select it.

Then in console we can do $r.deleteFish(‘fish1’); and it will disappear from the menu and from the inventory.

We need to get deleteFish function down to the EditFishForm button component.

It is going to work exactly the same as the rest of them did. Add deleteFish as prop to Inventory in App. Then in inventory pass it down as a property for the EditFishForm. Within EditFishForm, on the button we will add an onClick. We can do it inline

<button onClick={() => this.props.deleteFish(this.props.index)}>
          Remove Fish
        </button>

22 - Animating React Components

Slack

In order, we imported TransitionGroup and CSSTransition from “react-transition-groups”. We replaced the ul element with but left the className and everything the same, that tells it what element to actually render out to the page

CSSTransition element needs property classNames, key and timeout

Stylst, like SASS but works with indentation

React is giving us these states as CSS classes and we can go ahead and use those CSS classes to add animation

If you need to reuse a transition group, you can put it in a variable.

If you want to put the transition options in a separate file because you are using the transition in many components, you can export it from that file and import it into this file and use it.


23 - Component Validation with PropTypes

With Proptypes we can validate the data that is being passed to ensure we are passing the right kind of data.

Example:

Header.propTypes = {
  tagline: PropTypes.string.isRequired
};

Typechecking With PropTypes – React

Header is a stateless functional component so we need to add PropTypes after, like so.

Fish is a regular React component so we can declare PropTypes as a variable. Since the proptypes are the same for all Fish components, we declare it as static so it lives on the momma component and we are not unnecessarily copying the proptypes to every single instance.

How to find props in the component? Search for this.props.

When you have a PropType that is an object, you could do PropType.object but then any object can work. Instead, if you know the properties of the object that you are expecting you can use

fish: PropTypes.shape({
      image: PropTypes.string,
      name: PropTypes.string,
      desc: PropTypes.string,
      status: PropTypes.string,
      price: PropTypes.number
    }),

24 - Authentication

In firebase, go to authentication and add Facebook authentication. Follow steps on Facebook apps to get app id, secret and past the auth url to the app config.

Stopped at 14:04 Import named and default export: import base, { firebaseApp } from "../base";

If we want to put the store into the variable and not the promise into the variable we put await in front of it.

storeId={this.props.match.params.storeId}

await base.post(${this.props.storeId}/owner, {

This will create a new field called owner if it does not already exist

52EE6C9F CEE4 4ABD 9A68 0565E687A2DF

Whenever anybody logs into a store, we are going to figure out who is the currently logged in user and who is the owner of the store? If they are the same people, we will let them manage or we will display the error message.

We set state on Inventory. Sometimes you don’t need state on any other component so what you do is create state that is local to that component.

If we refresh, everything is gone.

Lets look at how we can show the inventory rendering out and how to persist that so when you refresh the page it will automatically log the user in.

Go to the render method of Inventory.js, we want to perform a check instead of returning inventory all the time.

 //1. check if they are logged in
    if (!this.state.uid)

Checks if state contains a userid. If not, return Login button or otherwise render inventory.

Try to login, it sets state, and then inventory is rendered out.

We only want to show that just if the currently logged in user is also the owner of that store.

Check whether currently logged in user matches the owner of the store:

//2. check if they are not the owner of the store
    if (this.state.uid !== this.state.owner) {
      return (
        <div>
          <p>Sorry you are not the owner!</p>
        </div>
      );
    }

We want logout button in two places: 1) if they are not the owner and 2) if they are managing the inventory

We need to add a logout button and we need to check it on page load.

Since we need it in two places, we will put it in a variable so we can reuse it.

const logout = <button onClick={this.logout}>Log Out!</button>; Then use it like {logout} within render method.

Then add logout method.

To actually log them out, we make it an async method because we want to first wait for them to first logout of firebase, and clear state.

  logout = async () => {
    console.log(“Logging out!”);
    await firebase.auth().signOut();
    this.setState({ uid: null });
  };

Logout of firebase: await firebase.auth().signOut();

Update state to set uid to null.

When we refresh, we should recheck if we are logged in.

Listen for the componentDidMount() like so:

componentDidMount() {
    firebase.auth().onAuthStateChanged(user => {
      if (user) {
        this.authHandler({ user });
      }
    });
  }

But for a split second it does show the login screen. If you wanted to skip that, you could have a loading screen.

Locking Firebase Down With Some Rules

In firebase, go to Authentication tab. Go to our database tab, and go to rules, you will see 0E56C053 86CD 4FF7 93DB 8F633279B28D

Firebase uses javascript to handle the rules. If you open securityRules.json.

// These are your firebase security rules - put them in the “Security & Rules” tab of your database
{
  “rules”: {
    // won’t let people delete an existing room
    “.write”: “!data.exists()”,
    “.read”: true,
    “$room”: {
      // only the store owner can edit the data
      “.write”:
        “auth != null && (!data.exists() || data.child(‘owner’).val() === auth.uid)”,
      “.read”: true
    }
  }
}

Explained: -for writing, we make sure that the data actually exists which won’t allow people to exist existing room. (They can write to it if the data does not exist). -there are nested rules -so the top level of the entire database is the write rules -someone can only write to a specific store if the data does not exist, if the store already exists they cannot create the store for a second time. -everybody can read that

-then we go one level deep into our actually stores. In this case he uses the variable called $room which is a wildcard which will match up against anything that is a second level deep. It can be named $store

“$room”: {
      // only the store owner can edit the data
      “.write”:
        “auth != null && (!data.exists() || data.child(‘owner’).val() === auth.uid)”,
      “.read”: true
    }

These rules above apply to second level deep.

Who can then write at a second level?

First we make sure that the authentication does not equal null (that auth variable comes from firebase since we are using their built in auth). Then we check if the data doesn’t exist AND that the owner is equal to the actual person that is logging in. Only the person who owns the store can write to it. Anybody can read that specific store.

Copy and paste security-rules.json and paste it in the rules .


Other

Rewatching #7 Passing Dynamic Data with Props

Header Component has prop tagline. Within Header, we access it using this.props.tagline. this means the component instance, so whatever gets passed when it is used.

For example within one component you may have many Headers like so:

The “this” within header is referring to that specific instance. So within the header component you would access what that instance’s tagline is using this.props.tagline.


8 - Stateless Functional Components (video 8, 1:40 seconds into it)

If your component only has a render method, no need for it to be a full blown React component.

First we will make it are regular function and then refactor it into ES6

from

class Header extends React.Comopnent{
render(){
return(
<header className="top">
<h1>
Catch of the day </h1>
<h3 className="tagline">
<span>{this.props.tagline}</span>
</h3>
</header>
);
}

to

function Header(props){
	return(
<header className="top">
<h1>
Catch of the day </h1>
<h3 className="tagline">
<span>{props.tagline}</span>
</h3>
</header>
);
}

The only thing is when you have a function there is no this, so what happens is that function gets one argument called props and you remove “this”.props and use {props.tagline} for example.

ES6 Arrow Function, no real benefit gained but most people write it like this.

const Header = (props)=>{
	return(
<header className="top">
<h1>
Catch of the day </h1>
<h3 className="tagline">
<span>{props.tagline}</span>
</h3>
</header>
);
}

We can take this one step further, and do an implicit return (we don’t need return keyword).

If we return it on the same line, that’s what an arrow function will do.

const Header = props =>(
<header className="top">
<h1>
Catch of the day </h1>
<h3 className="tagline">
<span>{props.tagline}</span>
</h3>
</header>
);

Destructuring props into own variables

const Header = ({tagline, age}) =>(
<header className="top">
<h1>
Catch of the day </h1>
<h3 className="tagline">
<span>{tagline}</span>
</h3>
</header>
);

10 - Helper & Utility Functions

When you have a function that does something like formatting money, or auto populating an input, which is not specific to react, it’s just a regular javascript function

Put those in a separate file.

Named export: you know the name of the method that you want to import, and then you have to use the {} syntax.

Instead of importing the entire file.

You can use that method inline then.

<input type=“text” defaultValue={getFunName()}/>

When the component mounts to the page, it will run getFunName() and then set the default value.


11 - Events

They are the same as javascript or JQuery, the one difference is you can do them inline.

Fore example, if you have a button that says “click me”.

In JS you would give it a class or id and then in a script file or later in the page you would select that button, add event listener or say .on in JQuery, listen for a click and then what that thing happens you would run some code.

In React what happens is you do inline event handlers..

<button onClick={}/>

So you do on[EventName] and give it {} and tell it which function to run when that thing happens.

Normally we will do {this.handleClick}

<button onClick={this.handleClick}>click me!</button> and above you would have

handleClick(){
alert(“heyyy”);
}

We leave out {this.handleClick()} the () that we used above in getFunName() because that would cause the function to execute when the component mounts, which is NOT what we want.

We just provide it the function, and say hey react when someone clicks this, run the function handleClick.

A ref is touching the Dom element to grab the reference.

Ref allows us in react to reference a Dom element.

Binding In React

let’s say you have

goToStore(event){
console.log(this)
}

render(){
console.log(this);
return (
<p>dummy</p>
);
}

The console.log(this) within the render method will return the store picker component, however the console.log(this) within the store picker component will not work. WHY?

Because of binding!

React has all these built in methods like render, and lifecycle events.

componentDIdMount = runs as soon as the component is put on the page.

Inside of componentDidMount, we can call console.log(this)and it will return the store picker component.

Why?

This is because all of the methods that come with React, all have the react component.

If we add any methods that extend that, they are not bound by default. Which means it’s hard to reference a component within it’s own methods which is a problem.

SOLUTION: Bind our own methods as well. Couple options… Because es6 classes are fairly new, there is no standard way to do this.

ES6 right now..

Add constructor method. This is a method that will run before the store picker component is created.

constructor(){
super()
this.goToStore = this.goToStore.bind(this);
console.log(this)
}

What that will do is overwrite the method on it, and attach a binding to it, it will reference this inside the store as the store picker instance.

this.goToStore = this.goToStore.bind(this);

Rather than using the constructor is, instead of declaring a method on the component we declare a property and set it to an arrow function.

A property will be bound to the instance rather than nothing, and then we can access this inside of it.

goToStore = event => {
console.log(this);
}

But to break it down, goToStore is a property just like myInput is a property. And then we set it to an arrow function which will allow us to bind the value of this to the storepicker component.

If you need to access this inside of a custom method, you must use that syntax or use a constructor.

So either arrow function or constructor.


12 - Handling Events

How do we access router within a component? There are a couple of different ways. One way is you can export your component with the router… (if it was a component that was 7 or 8 levels deep, it would be hard)

There is no way to access something from a high level to a low level.

Since storepicker is a child of the router, we have access to all the methods that we need.


Firebase

-using websockets instead of Ajax where we ping the db for changes

firebaseApp.database()


LocalStorage

Added code to two methods, componentDidUpdate() and componentDidMount().

componentDidUpdate we update the local storage to match by doing

localStorage.setItem(this.props.match.params.storeId, JSON.stringify(this.state.order));

To reinstate localStorage, we do it on componentDidMount(){

const localStorageRef = localStorage.getItem(params.storeId);
if(localStorageRef){
this.setState({order:JSON.parse(localStorage));

In react, if you return null it will render out nothing.


25 - Building For Production

Stop running the dev environment. In packages.json there is a build command, which right now is react-scripts build.

In the directory, in the terminal run npm run build.

That will take all of our files, css, javascript and compile it into a tiny javascript file that has stripped out warnings, prototypes etc.

If you navigate to the build directory, all the files inside of it are to be deployed.

That /build/javascript/js/ contains a file for that entire application. There is a source map file which will point back to where the errors are but only devs will load it.

It gives us a media folder with the images, the fonts we use. The css folder has the .css file. That is web pack doing that.

The index.html points to all of the files.

The build/ directory is almost a static site. However, if you try to open it up it doesn’t run. That is because the code still needs to be run on a server. The server needs to be smart enough not to look into look for directories based on the urls, we have to tell it to go back to the index.html side and figure out the routing from there.


26 - Deploying to Now

Now requires you to bring the server, it doesn’t have a server built in, you have to bring a server that handles all the server side routing for them. They have a package called serve.

First install now globally using npm i -q now

Next we need to require a local dependency called serve. npm i serve

It will add it to our list of dependencies.

Then we need to modify npm scripts because the start command is for development.

In packages.json, modify the “start” command to be the “dev” command. ScreenShot2019 04 05at11 58 37

   "dev": "react-scripts start",
    "start": "serve --single ./build",

We use —single to tell it that it’s a single page application and to go into the build folder.

Two things will happen when we deploy this. It will run the build command (it knows to do that) and then the start command.

Now you just run now in the terminal.

It will start deploying it and give us a temporary url

C46413F3 17E1 422A 99D3 882A2010F736

These instructions don’t seem to work still.


Hey folks! I ran into a few snags trying to deploy my site with Now. Authentication was working locally but, once the site deployed to prod, I wasn’t able to sign in to view my lovely fish. Here’s how you can fix that:

Make sure you’ve got the latest versions of package.json and now.json in your project. You can get those here: https://github.com/wesbos/React-For-Beginners-Starter-Files/tree/ca5802e4556fc3af48f78e5d0a053da880d7c2a5/catch-of-the-day

However, now.json is missing routes for images. You’ll want to add the following (I added this as a comment to the PR in Github):

{ "src": "^/images/(.*)", "dest": "/images/$1" },

  1. Run now. After it builds, you should be able to point to https://[appname].[username].now.sh. You can find this in https://zeit.co/dashboard

  2. Go to Firebase > Authentication > Sign-in method > Add domain. Enter the domain referenece above: https://[appname].[username].now.sh

Edited for clarity


27 - Deploying to Netlify

Install globally: npm i netlify-cli -g

Check version netlify --version

In directory, run netlify deploy It will prompt you to authorize.

Then follow the prompts. Point the path to deploy to the build directory

3EE72261 A0A0 426F A0AD 4CF951A5A581

Now it is deployed!

However, if you reload the page, you get an error.

https://5ca786631b5c190184ca18ee—catch-of-the-day-anja.netlify.com/store/sparkling-glamorous-teeth

Netflixy is actually looking for those directories. What we need to do, is in our build folder we need to make a file called redirected.

$ cd build
$ touch _redirects
$ code _redirects

In their docs Redirects | Netlify find HISTORY PUSHSTATE AND SINGLE PAGE APPS

Add this line to redirects /* /index.html 200

Save and cd out of build directory. Run netlify deploy

It should work now!


28 - Deploying to an Apache Server

Hav a folder on your server called catch of the day. Point it to a subdomain.

Take the build folder and upload it to that directory.

We need to add the subdomain to firebase authentication -> sign in method -> add domains

However when you refresh the page, we will get a 404.

Create a .htaccess file.

Add the following:

RewriteBase /
RewriteRule ^index\.html$ - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.html [L]

29 - Ejecting from Create-React-App

Create-React-App takes away the complexity of config files, builds a common default and puts it behind it’s own package called react scripts.

However, what if you want to do something custom, like custom web pack or eslint or babel plugins.

If and when you need to do that, you need to eject from create-react-app.

Ejecting is one way. Do this on a branch in git.

Run npm run eject

48106A5E 1ED8 4871 A002 31C8608F04BF

It edited package.json and it edited config/ and scripts/ directory.