React For Beginners β ReactForBeginners.com
Starter files for the React For Beginners course. Come Learn React with me!
The code in this repo meant to be a reference point for anyone following along with the video course.
- cd into
catch-of-the-day
and follow along with the videos - launch server by running
yarn install
Component is a reusable piece of your website. React dev tools can show you the custom components of a React site. Designers can work on seperate components. Components can have data and event listeners.
App component is the parent component. It contains all the fish in the state. Changes in state are reflected across the entire app.
Build our first component StorePicker
. Our mount point is the div#main
. We use the render
method to tell React where to send the component.
render(<StorePicker/>, document.querySelector('#main') )
StorePicker component
import React from 'react'
class StorePicker extends React.Component {
render() {
return <p>Hello</p>
}
}
export default StorePicker
Recommend to store components seperately in the src/components/StorePicker.js
Then we import it to our index.js like this:
import StorePicker from './components/StorePicker'
We work more on our StorePicker component using JSX. In the render
method, we can only have one parent element and the entire block must be wrapped in ()
.
Classes are added by using the <form className="store-selector">
since class
is reserved by javascript.
Comments are made by {/* JSX COMMENT */}
Add styles
Adds Header
, Order
, and Inventory
components to our main App
component.
We pass data to our components via props
.
// in our App component we pass props
<Header tagline="Fresh Seafood Market"/>
// in our Header component we access props
<h3 className="tagline">{this.props.tagline}</h3>
Stateless functional components can be used for simple rendering html to the DOM.
We can refactor our Header component to a stateless component by:
- by removing the
class
andrendor
method - Add a const named Header and arrow function
- pass in
props
in the parameters
const Header = (props) => {
return (
<header className="top">
<h1>
Catch
<span className="ofThe">
<span className="of">of</span>
<span className="the">the</span>
</span>
Day
</h1>
<h3 className="tagline"><span>{props.tagline}</span></h3>
</header>
)
}
React Router is used to show and hide components anywhere in your application depending on the url. Everything in React is a component even React Router.
import { BrowserRouter, Match, Miss } from 'react-router'
<BrowserRouter>
<div>
<Match exactly pattern="/" component={StorePicker} />
<Match pattern="/store/:storeId" component={App} />
<Miss component={NotFound}/>
</div>
</BrowserRouter>
Events are attached inline using onClick or onSubmit evcent handler.
Get access to form data using a ref.
Ok so to reference this in your custom methods you would setup a contructor to bind to this.
class StorePicker extends React.Component {
constructor() {
super()
this.goToStore =this.goToStore.bind(this)
}
goToStore( event ) {
event.preventDefault()
// grab text from the box
console.log(this.storeInput)
}
//Form input
<input type="text" required placeholder="Store Name" defaultValue={ getFunName() } ref={ (input) => {this.storeInput = input} } />
}
Or you can bind this directly on the form submit and remove the constructor.
<form className="store-selector" onSubmit={ this.goToStore.bind(this) } >
In order to route our form to new url we bring in the router. React Router could use Redirect component or you can use an imperative api.
You can gain access to the router in your component
StorePicker.contextTypes = {
router:React.PropTypes.object
}
then in our goToStore method we use the router to the store
//transition from / to /store/:storeId
this.context.router.transitionTo(`store/${storeId}`)
React uses html push state so the page doesn't reload itself
This will be a video you watch over and over π π π
State is a representation of your data in the app. Each component can have its own state. Think of it as one object that holds all of the data.
We need to share State with other components so a good place to do that is your Master component and for us that is the App Component.
GetInitialState is a way to let React know of the different states for the app. We add it to the App class via a constructor.
Pass things down to child components via props.
If you want to loop over something, you need an array Object.keys
and loop via .map
. This method takes in a key and outputs Fish components. React will yell at you if the component are not unique so we do that by adding the key={keys}
. We pass the state of the fish via details
.
<ul className="list-of-fishes">
{
Object
.keys(this.state.fishes)
.map(key => <Fish key={key} details={this.state.fishes[key]} />)
}
</ul>
Update our Fish component to dynamically set Add to Order functionality based on the fish's availablity.
We build an addtoOrder
method in the App.js file. It adds one pound of the selected fish and adds it to the order state.
To invoke the addToOrder
method we can't use key
from the props we send to the component. Instead we have to create our own and in this case we make one up called index={key}
.
To build the Order compoment we need to pass in the fishes and the order state. In our Order component we build logic to calculate the total order and display the fish and appropriate pounds.
In this lesson we setup firebase which will be our realtime backend for our fishes state.
After we create our firebase project we add the apikey, authDomain, and databaseURL to a new file called /src/base.js
.
In our app.js
we will use React's componentWillMount method to connect to firebase. To learn more about Reacts component states goto the docs.
We also learn to use componentWillUnmount when we connect to a different store.
componentWillMount()
{
this.ref = base.syncState(`${this.props.params.storeId}/fishes`,
{
context: this,
state: 'fishes'
})
}
componentWillUnmount()
{
base.removeBinding(this.ref)
}
We can store order data using html5 local storage. We'll use Reacts lifecycle hooks to keep track of state via componentWillUpdate. This will run whenever props or state changes.
To store items in html5 local storage we use localStorage which stores key-value pairs.
localStorage.setItem('frank', 'is really cool') // to set an item
and then to retrieve it we use
localStorage.getItem('frank') // is really cool
Since we can't store objects in localStorage we have to convert it to a string via stringify.
componentWillUpdate(nextProps, nextState)
{
// set our local Storage
localStorage.setItem(`order-${this.props.params.storeId}`,
JSON.stringify(nextState.order))
}
then when we retrive localStorage we have to convert to an object via parse
// check if there is any order data in local Storage
const localStorageRef = localStorage.getItem(`order-${this.props.params.storeId}`)
if (localStorageRef) {
// update our order components order state
this.setState({
order: JSON.parse(localStorageRef)
})
}