diff --git a/images/antsGoMarching.png b/images/antsGoMarching.png new file mode 100644 index 0000000..f93eade Binary files /dev/null and b/images/antsGoMarching.png differ diff --git a/images/full_component_lifecycle.png b/images/full_component_lifecycle.png new file mode 100644 index 0000000..1f1cbfd Binary files /dev/null and b/images/full_component_lifecycle.png differ diff --git a/images/full_reactjs_component_lifecycle.png b/images/full_reactjs_component_lifecycle.png new file mode 100644 index 0000000..0b88a86 Binary files /dev/null and b/images/full_reactjs_component_lifecycle.png differ diff --git a/images/react_component_lifecycle.jpg b/images/react_component_lifecycle.jpg new file mode 100644 index 0000000..2d13bf1 Binary files /dev/null and b/images/react_component_lifecycle.jpg differ diff --git a/images/react_lifecycle b/images/react_lifecycle new file mode 100644 index 0000000..5301f1c Binary files /dev/null and b/images/react_lifecycle differ diff --git a/images/react_lifecycle.png b/images/react_lifecycle.png new file mode 100644 index 0000000..5301f1c Binary files /dev/null and b/images/react_lifecycle.png differ diff --git a/images/react_simple_component_lifecycle.png b/images/react_simple_component_lifecycle.png new file mode 100644 index 0000000..b386c43 Binary files /dev/null and b/images/react_simple_component_lifecycle.png differ diff --git a/images/reactjs_component_lifecycle.html b/images/reactjs_component_lifecycle.html new file mode 100644 index 0000000..e318211 --- /dev/null +++ b/images/reactjs_component_lifecycle.html @@ -0,0 +1,19 @@ + Google Image Result for http://image.slidesharecdn.com/ypyfe-150523113716-lva1-app6891/95/react-16-638.jpg?cb=1432381135
\ No newline at end of file diff --git a/images/reactjs_component_lifecycle.jpeg b/images/reactjs_component_lifecycle.jpeg new file mode 100644 index 0000000..58a7df6 Binary files /dev/null and b/images/reactjs_component_lifecycle.jpeg differ diff --git a/images/what-is-webpack.png b/images/what-is-webpack.png new file mode 100644 index 0000000..519ed22 Binary files /dev/null and b/images/what-is-webpack.png differ diff --git a/lesson 13 - React Part1.md b/lesson 13 - React Part1.md index 7c0f8b9..75898dc 100644 --- a/lesson 13 - React Part1.md +++ b/lesson 13 - React Part1.md @@ -1,4 +1,4 @@ -# Lesson 14 - React +# Lesson 13 - React ## Recap & Intro - We've come a long way! We've learned @@ -17,7 +17,7 @@ - Simple, powerful, and composable ## What React Isn't -- React is not a web framework (not tied to html/css). +- React is not a web framework (not tied to html/css). - React isn't a full fledged application framework - React is not Flux or Redux @@ -73,7 +73,7 @@ Like we said before, JSX isn't really HTML. Because it lives in the same context - All tags have to be closed. `` for example, has to include a closing tag ``. ## Exercise 1: Rendering a Simple Component -Let's create our first component! +Let's create our first component! 1. Clone the boilerplate project from `git@github.com:ttsJavaScriptApps/webpack-boilerplate.git` 2. In index.jsx, create a component class called `MessageInput` that renders: @@ -85,7 +85,7 @@ Let's create our first component! ## Making our JSX Dynamic Let's take a deeper look at the render method. This is essentially the equivalant of our view template in other frameworks (ejs, handlebars, mustache, jade, haml, etc.). -The basic functionality needed in any templating language is +The basic functionality needed in any templating language is 1. Token Replacement 2. Conditions @@ -103,7 +103,7 @@ class HelloMessage extends React.Component { constructor() { super(); //needed for inheritance - + //Define an intial state object this.state = { message : 'Hello World' @@ -152,13 +152,13 @@ Often times we want to render one thing in one case, and something else in anoth // this.state = { person : 'Matt'}; render() { - + //Figure out the elements in advance if(this.state.person) message = "Hello " + this.state.person; else message = "I'm all alone... and sad"; - + return (
{message}
); @@ -189,12 +189,12 @@ Sometimes you want to render the same elements repeatedly for every item in an a ```javascript //this.state = { studentNames: ['Matt', 'Katy', 'Mariel', 'Lee'] } -render() { +render() { //Figure out the elements in advance var students = this.state.studentNames.map(function(name){ return (
  • {name}
  • ) }) - + return ( ); @@ -211,12 +211,12 @@ One of the most common dynamic elements is the list of classes an element has ap render() { var classes = 'item' - + if(isActive) { classes += 'active'; } - - + + return (
    ); @@ -233,8 +233,8 @@ render() { var classes = classNames({ 'item' : true, 'active' : isActive - }) - + }) + return (
    ); @@ -251,7 +251,7 @@ render() { color: 'red', textDecoration: 'underline' } - + return (

    ); @@ -270,7 +270,7 @@ Let's add some logic to our little component. 5. Only show the most recent 3 messages. 6. If there are more than 3 messages, show a "load more" button -## Homework +## Homework - Start Reading the [React Documentation](https://facebook.github.io/react/docs/getting-started.html) - Complete the first 3 challenges (stop at Step 2 - Part 3) of [Thinking in React](https://github.com/asbjornenge/thinking-in-react) module diff --git a/lesson 16 - React Part 4.md b/lesson 16 - React Part 4.md new file mode 100644 index 0000000..3512c07 --- /dev/null +++ b/lesson 16 - React Part 4.md @@ -0,0 +1,542 @@ +# React Component LifeCycle & React Router + + +## Recap & Intro +- Last week focused on: + - State + - Props + - Component Composition +- Tonight we'll be discussing React LifeCycle and React Router + + +## Agenda + +- Cover the full spectrum of LifeCycle events in React +- Discuss how to render different views (in a single page application) + +## Lifecycle events + +So, what are Component LifeCycle Events? While it sounds scary, the concept is actually quite simple. + +Below are the 4 stages of the React LifeCycle: + +![](./images/react_lifecycle.png) + +Before we dive in though, let's review props and state + +### Props vs State + +#### Review of Props and State + +If a Component needs to alter one of its attributes at some point in time, that attribute should be part of its state, otherwise it should just be a prop for that Component. + +**props**: + +props (short for properties) are a Component's configuration, its options if you may. They are received from above and immutable as far as the Component receiving them is concerned. + +A Component cannot change its props, but it is responsible for putting together the props of its child Components. + +**state**: + +The state starts with a default value when a Component mounts and then suffers from mutations in time (mostly generated from user events). It's a serializable* representation of one point in time—a snapshot. + +A Component manages its own state internally, but—besides setting an initial state—has no business fiddling with the state of its children. You could say the state is private. + +## Component Initialization + +You are familiar with the instantiation of a component. + +```javascript +class HelloMessage extends React.Component { + constructor(){ + super(); + } + + render(){ + return( +

    Hello World

    + ) + } +} +``` + +When a component is instantiated, the `render()` method - along with 4 other methods - are called. + +Those methods are: + +- `getInitialState()` ***this has been deprecated in favor of `this.state` in your constructor method*** +- `getDefaultProps()` ***(also deprecated in favor of ES6 instance methods)*** +- `componentWillMount()` +- `componentDidMount()` + +Obviously, you understand render, so lets dig into the other methods + +### this.state = {} + +As stated above, `getInitialState` has been replaced with `this.state`, however, I believe that looking at the `getInitialState` syntax will help bring a bit of clarity to the LifeCycle + +Let's create a basic counter that, when clicked, will count up + +##### with: getInitialState +```javascript +var Counter = React.createClass({ + getInitialState: function() { + console.log('getInitialState just ran!'); + return {count: 0}; + }, + + countUp: function() { + this.setState({count: this.state.count + 1}); + }, + + render: function() { + return ( +
    +

    {this.state.count}

    +
    + ) + } +}); + +let mountPoint = document.getElementById("root"); +ReactDOM.render(, mountPoint) +``` + +`getInitialState` fires as soon as the component is instantiated. However, it does not run again throughout the life of the component. + + +let's throw a couple of `console.log()`'s in to further illustrate the point. + +```javascript +var Counter = React.createClass({ + getInitialState: function() { + console.log('getInitialState just ran!') + return {count: 0}; + }, + ... + render: function() { + console.log('render just ran!'); + return ( + ... + ) + } +}); +``` + +In an effort to make React line up more with ES2015 (and future versions of JavaScript) `getInitialState` has been replaced with simply declaring `this.state =` in your constructor method. + + +##### with: this.state +```javascript +class Counter extends React.Component { + constructor(props) { + super(props); + this.state = {count: 0}; + console.log('state has been intialized!'); + } + + countUp() { + this.setState({count: this.state.count + 1}); + } + + render() { + console.log('render just ran!'); + return ( +
    +

    Clicks: {this.state.count}

    +
    + ); + } +} + +let mountPoint = document.getElementById("root"); +ReactDOM.render(, mountPoint) +``` + +### defaultProps + +As stated in the intro, `defaultProps` was formerly known as `getDefaultProps` + +`defaultProps` does exactly what you would think... it defines default props being made available to the component. + +Assigning default props is as simple as declaring `YourClass.defaultProps` and passing an object. + +```javascript +class Counter extends React.Component { + constructor(props) { + super(props); + console.log('State has been intialized!'); + this.state = {count: this.props.initialCount}; + console.log('Default Props assigned!'); + } + countUp() { + this.setState({count: this.state.count + 1}); + } + render() { + console.log('render just ran!'); + return ( +
    +

    Clicks: {this.state.count}

    +
    + ); + } +} + +Counter.propTypes = { initialCount: React.PropTypes.number }; +Counter.defaultProps = { initialCount: 0 }; +``` + +`defaultProps` and `propTypes` are considered properties on the constructor method. Which is why we can pass props to `super()` + +### componentWillMount + +`componentWillMount` is called *before* `render` is executed + +This is the part of the lifecycle where props and state values are interpreted to create the correct output. Meaning that state/props should should be modified inside this function. + +According to the [React Documentation](https://facebook.github.io/react/docs/component-specs.html): +> If you call `setState` within this method, `render()` will see the updated state and will be executed only once despite the state change. + +```javascript +class Counter extends React.Component { + ... + + componentWillMount(){ + console.log('componentWillMount just ran!'); + } + render() { + ... + } +} +``` + +### componentDidMount + +Immediately after the `render` method has been invoked, the `componentDidMount` function is called. + +`componentDidMount` is where you should place your DOM interactions and AJAX calls. + +```javascript + class Counter extends React.Component { + + ... + + componentDidMount(){ + console.log('componentDidMount just ran!'); + setTimeout(function(){ + console.log('running the setTimeout method!'); + }, 2000); + } + + render() { + ... + } +} +``` + +This summarizes the LifeCycle events being triggered during Component Instantiation. + +## setState and props Changed + +`setState` triggers the state change LifeCycle events, while updates to props triggers the `componentWillReceiveProps` method + +Updates to **state** and **props** contain 3 additional LifeCycle methods: +- `shouldComponentUpdate` +- `componentWillUpdate` +- `componentDidUpdate` + +### shouldComponentUpdate + +`shouldComponentUpdate` is **boolean** method that isalways called before `render`. + +The purpose of `shouldComponentUpdate` is to determine if re-rendering is needed. + +`shouldComponentUpdate` takes 2 arguments: + +- nextProps +- nextState + +These arguments are used to detect when re-rendering is needed. + +```javascript +class Counter extends React.Component { + + ... + + shouldComponentUpdate(nextProps, nextState){ + console.log(`shouldComponentUpdate is running! + nextState: ${JSON.stringify(nextState)}`); + + return true; + } + render() { + ... + } +} +``` +*note: if the `shouldComponentUpdate` method is invoked, you must return a boolean value* + +### componentWillUpdate + +As soon as `shouldComponentUpdate` returns `true`, `componentWillUpdate` is invoked. In many ways, you could consider this a cousin to the `componentWillMount` method. + +Calls to to trigger state changes, (ie: `this.setState`) are not allowed in `componentWillUpdate`. + + +Think of `componentWillUpdate` as a way to prepare for upcoming changes to state. + +```javascript +class Counter extends React.Component { + ... + + componentWillUpdate(nextProps, nextState){ + console.log(`preparing for the upcoming state change! + this.state: ${JSON.stringify(this.state)} + nextState: ${JSON.stringify(nextState)}`); +} + + render() { + ... + } +} +``` + +### componentDidUpdate + +At this point, you should be able to pretty clearly guess the behavior of `componentDidUpdate`. + +The functionality of `componentDidUpdate` is very similar to `componentDidMount`(with the exception that `componentDidUpdate` is called each time the component is re-rendered). Any interactions with the DOM (after re-rendering) should take place within this method + +Additionally, you'll notice that `prevProps` and `prevState` are passed as arguments + +```javascript +class Counter extends React.Component { + ... + +componentDidUpdate(prevProps, prevState) { + console.log('componentDidUpdate just ran!'); +} + + render() { + ... + } +} +``` + +### componentWillReceiveProps + +`componentWillReceiveProps` runs prior to the above state change methods and is only invoked when changes are made to props. + +Before we go any further, let's change up the code and try out a new example with multiple components. + +#### index.js +```javascript +import React from 'react'; +import ReactDOM from 'react-dom'; + +writeToScreen('Initial', 'primary'); + +class Counter extends React.Component{ + constructor(props){ + super(props); + writeToScreen('GetInitialState', 'info'); + writeToScreen('GetDefaultProps', 'info'); + this.state = { + foo : 1 + }; + } + + componentWillMount() { + writeToScreen('ComponentWillMount', 'warning'); + } + + componentDidMount() { + writeToScreen('ComponentDidMount', 'warning'); + } + + shouldComponentUpdate() { + writeToScreen('ShouldComponentUpdate', 'info'); + return true; + } + + componentWillReceiveProps(nextProps) { + writeToScreen('ComponentWillRecieveProps', 'warning'); + } + + componentWillUpdate() { + writeToScreen('ComponentWillUpdate', 'warning'); + } + + componentDidUpdate() { + writeToScreen('ComponentDidUpdate', 'warning'); + } + + componentWillUnmount() { + writeToScreen('componentWillUnmount', 'danger'); + } + +updateState() { + writeToScreen('Updating State', 'primary'); + this.setState({foo: this.state.foo + 1}); +} + +render(){ + writeToScreen('Render', 'success'); + return ( +
    +

    This.state.foo: {this.state.foo}

    +

    This.props.bar: {this.props.bar}

    +
    + + +
    + )} +} + +Counter.defaultProps = { bar: 0 }; + +class App extends React.Component{ + constructor(){ + super(); + this.state = {id : 1}; + } + + unmount() { + writeToScreen('Unmounting', 'primary'); + ReactDOM.unmountComponentAtNode(document.getElementById('root')); + } + + updateProps() { + writeToScreen('Updating Props', 'primary'); + this.setState({id: this.state.id + 1}); + } + + render() { + return ( +
    +
    + +
    + + +
    + +
    + ) + } +} + +function writeToScreen(msg, level) { + var elem = document.getElementById('screen'); + elem.innerHTML += '
    ' + + '   ' + + msg + + '
    '; +} + +let mountPoint = document.getElementById("root"); +ReactDOM.render(, mountPoint) +``` + +#### index.html +```html + + + + + + + + + + + +
    +
    + + + +``` + +*At this point, it would be better to switch to the React Dev Tools to inspect the state and props of each component* + +Above, we are calling the `componentWillReceiveProps` method each time we click the Update Props button. + +This method runs and each subsequent state change method is invoked afterwards. + +### componentWillUnmount + +Again, you should have a pretty clear sense of what `componentWillUnmount` is going to accomplish. + +This method removes the component from the DOM. + +In your `` component, add the following: + +```javascript +class App extends React.Component{ + constructor(){ + ... + } + unmount() { + writeToScreen('Unmounting', 'primary'); + ReactDOM.unmountComponentAtNode(document.getElementById('root')); + } + + updateProps() { + ... + } + + render() { + return ( +
    +
    + +
    + + +
    + ) + } +} +``` + +For fun, we can also add the following code to our `App` component: + +```javascript + componentDidUpdate(prevProps, prevState) { + setInterval(this.updateProps.bind(this),500); + } +``` + +This will show that our app will continue to make calls even after the app is no longer mounted. While it serves no *real* purpose, this should show you the power of Mounting/UnMounting Components. + + + +Now that you've had a chance to review the React LifeCycle, let's look at a more detailed image: + +![](./images/full_component_lifecycle.png) + + +## Homework + +- Complete the [ReactJS Koans](https://github.com/arkency/reactjs_koans) exercies +- Read the following article on [shouldComponentUpdate](http://buildwithreact.com/article/optimizing-with-shouldcomponentupdate) diff --git a/lesson 17 - React Part 5.md b/lesson 17 - React Part 5.md new file mode 100644 index 0000000..3be56fe --- /dev/null +++ b/lesson 17 - React Part 5.md @@ -0,0 +1,231 @@ +## React Router + + +## Intro & Recap + +- Last class, we discussed the React Component LifeCycle. +- This includes: + - Component Instantiation + - Updates to State + - Updates to Props + - Unmounting Components +- Which leads us into tonight's topic: React Router + +## Agenda + +- Understand the purpose of React Router +- When to use React Router +- How to implement React Router + +## The Purpose of React Router + +Due to the fact that React is a library (not a complete framework), it does not aim to solve all an application's needs. + +While React does a great job at creating components and providing a system for managing state (in Single Page Applications, you still need a way of changing URL's and rendering new components (based on User Interaction) + +The best solution for this is the React Router Library. + +According to the React Router Documentation: + +> React Router is a powerful routing library built on top of React that helps you add new screens and flows to your application incredibly quickly, all while keeping the URL in sync with what's being displayed on the page. + +In short, React Router takes care of rendering components for us. + +Let's dig in: + +### Install and Import React Router + +You'll need to install React Router through NPM + +`npm install react-router --save-dev` + +Next, you'll want to import the appropriate variables. + +```javascript +import React from 'react'; +import ReactDOM from 'react-dom'; +import { Router, Link, Route } from 'react-router'; + +``` + +That's it for setup! + + +### Component Configuration + +We're going to utilize 3 components + +Starting with a NavBar component + +```javascript +class NavBar extends React.Component{ + render(){ + return( +
    + Home + Login +
    + ) + } +} +``` +You'll notice here that we've used the `` component. This has been pulled directly from the React-Router library. + +- `` replaces `` +- This provides a standard HTML anchor tag when the DOM renders +- Using `` is **necessary** for React Router to implement the routing magic that we are looking for. + + + +Next, we'll create a Welcome Component, asking the user to Login + +```javascript +class Welcome extends React.Component{ + render() { + return ( +
    + +

    Press Login To Continue

    +
    + ); + } +} +``` + +In the above example, we've brought our NavBar component in as a child component. + + +Finally, we'll create a Login Component (for when the User is Logged In) + +```javascript +class Login extends React.Component{ + render() { + return( +
    + +

    You are now Logged In

    +
    + ); + } +} +``` + +### Configure the Routes + +While on the surface, this appears to be difficult, it's surprisingly simple + +Step one is creating the Router + +```javascript +let routes = ( + +) +``` +We've assigned the `` component to a variable named `routes` + + +Next, we'll nest ``'s as children of the `` + +```javascript +let routes = ( + + + + +); +``` + +### Render the Router + +In our ReactDOM.render method, we'll just need to pass in the `routes` variable as our first argument + +```javascript +let mountPoint = document.getElementById("root"); +ReactDOM.render(routes, mountPoint) +``` + +This allows React Router to handle rendering the appropriate components. + +### History + +You've probably noticed that the URL bar has really random strings appended to the end of your URI. This is through a concept known as hashHistory. Essentially, the `#` is used to manage routing performed on the client side. + +Currently, The React Router documentation recommends using `browserHistory` to address this issue, and clean up the URL's. + +```javascript +import { Router, Link, Route, browserHistory } from 'react-router'; + + ... + +let routes = ( + + ... + +); +``` + +With browserHistory implemented, your `` component knows which *history tracking* stragety to use, and makes the URL looks significantly better. + + +## Exercise and Homework + +- Work with your partner to complete the [React Router Tutorial](https://github.com/ttsJavaScriptApps/React-Router-Tutorial) +- Clone the repo +- Create a new branch +- Push the changes back up to the class GitHub repo + + +### Full Code Sample: + +```javascript +import React from 'react'; +import ReactDOM from 'react-dom'; +import { Router, Link, Route, browserHistory } from 'react-router'; + +class NavBar extends React.Component{ + render(){ + return( +
    + Home + Login +
    + ) + } +} + +class Welcome extends React.Component{ + render() { + return ( +
    + +

    Press Login To Continue

    +
    + ); + } +} + + +class Login extends React.Component{ + + render() { + return( +
    + +

    You are now Logged In

    +
    + ); + } +} + + +let routes = ( + + + + +); + + +let mountPoint = document.getElementById("root"); +ReactDOM.render(routes, mountPoint) +``` diff --git a/lesson 18 - Firebase.md b/lesson 18 - Firebase.md new file mode 100644 index 0000000..8baf634 --- /dev/null +++ b/lesson 18 - Firebase.md @@ -0,0 +1,333 @@ +# Lesson 18 - Firebase + +## Recap & Intro +- We've learned a lot about React +- Last lesson, we learned how to get data into our React components +- Today we'll learn how to integrate a real-time data source +- We'll also learn how to deploy our application + +## What is Firebase +Firebase is a back end as a service (BaaS) platform. It provides: + +- Hosting for your static application +- Data read/write +- User Authentication + +## Hosting +Your React app is static, meaning that it doesn't have to run any code on the server. All a server needs to do is host your files and provide them to a client when requested. Firebase does this for you easily. + + +## Exercise 1: Deploying your app +1. Sign up for firebase using your Google account at [http://www.firebase.io](http://www.firebase.io) +2. Install Firebase tools using your commandline - `npm install -g firebase-tools` +3. Log in to your firebase account from commandline `firebase login` +4. From your React application directory, create a new Firebase app by running `firebase init` (tell firebase where your dist directory is) +5. Deploy using `firebase deploy` +6. See your app by running `firebase open` + +## Data +A Firebase data store can be thought of simply as a JSON object in the cloud. When you create a Firebase application, a URL is created that represents the root node of the JSON object. To work with it, you need to create a "Ref" + +```javascript +var ref = new Firebase("https://tts-demo.firebaseio.com/"); +``` + + +### Writing Simple Data + +```javascript +var ref = new Firebase("https://tts-demo.firebaseio.com/"); + +ref.set({ + message: 'hello world' +}); +``` + +If you go to https://tts-demo.firebaseio.com/, you'll see that the data's been saved. + +The example above replaces the data completely. Instead, you can provide an object with a partial set of keys to update. + +```javascript +var ref = new Firebase("https://tts-demo.firebaseio.com/"); + +ref.set({ + className: 'JS', + weeks: 10 +}); + +ref.update({ + className: 'JS Application Development', + students: 15 +}); + +/* Ref is now +{ + className: 'JS Applications', + weeks: 10, + students: 15 +} +*/ + +``` + +### Reading Simple Data +Because Firebase is real-time, you don't request data in a discrete way like you do from a REST API. Instead, you listen for events on your data that signal when the data has been updated and run a callback when that happens. + +For example, we can run a callback function every time our JSON object is changed + +```javascript +ref.on("value", function(snapshot) { + console.log(snapshot.val()); +}) +``` + +**Note - Events are fired immediately for existing data.** + +### Child References +Most times, you don't want to listen to the whole JSON object, just a specific subsection. You can create a reference to a portion of your JSON object by using the reference's `child()` function. + +Let's say your data looks like this: + +```javascript +{ + class: 'JS Applications', + teacher: { + name: 'Shane', + computer: { + type: 'mac', + size: '15 inch' + } + } +} +``` + +You can read and listen for changes in just the `teacher` object by creating a child reference like this: + +```javascript +var ref = new Firebase("https://tts-demo.firebaseio.com/"); +var teacher = ref.child('teacher'); +teacher.on('value', function(v){/*... */}) +``` + +Child paths can be nested as deeply as you'd like. + +```javascript +var ref = new Firebase("https://tts-demo.firebaseio.com/"); +var ShanesComputer = ref.child('teacher/computer'); +``` + + +## Firebase with React +Let's add Firebase data to a React component. Let's start with a simple controlled component. + +```javascript +import React from 'react'; +import ReactDOM from 'react-dom'; +import classNames from 'classnames'; + +class MessageApp extends React.Component { + constructor() { + super(); + this.state = { + inputValue: '' + } + } + + _handleChange(event) { + this.setState({ + inputValue: event.target.value + }) + } + + render() { + + return ( +
    + +
    + ) + } +} + +var mountPoint = document.querySelector("#app"); +ReactDOM.render(,mountPoint) +``` + +#### Install Firebase +Next, we'll bring in Firebase via npm `npm install --save firebase`. We can now import firebase just like all of our other dependencies + +```javascript +import React from 'react'; +import ReactDOM from 'react-dom'; +import classNames from 'classnames'; + +//Import firebase! +import Firebase from 'firebase'; + +//... +``` + +#### Create a ref +For now, let's have our component create a firebase reference. + +```javascript + constructor() { + super(); + + this.state = { + inputValue: '' + } + + this.ref = new Firebase("https://tts-demo.firebaseio.com/"); + } +``` + +#### Get Data from Firebase +We can bring in data from Firebase in the `componentDidMount` event. + +```javascript +componentDidMount(){ + + //Arrow function so callback can use component's this.setState + ref.on("value", (snapshot) => { + this.setState({ + inputValue: snapshot.val() + }) + }) +} +``` +This creates a 1-way data binding from firebase to the component. That is, every time Firebase is updated, the component's state will be updated. + +#### Update data in Firebase +If we want updates to be saved to firebase, we'll have to update our reference object. + +```javascript +_handleChange(event) { + this.ref.update({inputValue: event.target.value}) +} +``` + +Notice that this.setState() isn't necessary! This is because your callback in componentDidMount will set update the component state for you. + +**Note - Your data is being updated in real time. Open another browser to the same local address and watch the magic happen** + +## Exercise 2: Binding data +Let's create a theme preview tool with React + +- Create a form with controlled text inputs for color and background +- Create a 'save' button +- Create a div (500px by 500px) with an h1 that reads 'This is a preview' +- When the 'save' button is clicked, save the two values currently in the inputs to a firebase reference +- Style the div to display the text color and background color stored in Firebase at all times +- Set up the inputs to contain the names of the text and background colors saved in firebase. + + +## Lists of data +One thing we haven't covered yet, is how to deal with arrays or lists with firebase. This is very similar to how we deal with other data, but with different events. We'll be using `ref.push(obj)` to write data and `child_added`, `child_removed` and `child_changed` events to read updated data + + +## Chat app +We'll start with our basic, one component, message app: + +```javascript +import React from 'react'; +import ReactDOM from 'react-dom'; +import classNames from 'classnames'; + +class MessageApp extends React.Component { + constructor() { + super(); + this.state = { + newMessageInput: '', + messages: [] + } + } + + _handleButton(event) { + var newMessage = this.refs.messageInput.value; + this.setState({ + messages: this.state.messages.concat(newMessage) + }) + } + + _handleChange(event) { + this.setState({ + newMessageInput: event.target.value + }) + } + + render() { + var messages = this.state.messages.map((message, i)=>{ + return
  • {message}
  • + }) + + return ( +
    +

    Slick

    + + +
      + {messages} +
    +
    + ) + } +} + +var mountPoint = document.querySelector("#app"); +ReactDOM.render(,mountPoint) +``` + +We're going to want to read and write the state.messages array from Firebase following the same steps are before: + +#### Import firebase +`import Firebase from 'firebase';` + +#### Create a reference to messages +```javascript +constructor() { + super(); + this.state = { + newMessageInput: '', + messages: ['hello', 'world'] + } + + this.messagesRef = new Firebase("https://tts-demo.firebaseio.com/messages"); +} +``` + +#### Get data in componentDidMount using 'child_added' event + +```javascript +componentDidMount(){ + this.messagesRef.on("child_added", (snapshot) => { + this.setState({ + messages: this.state.messages.concat(snapshot.val()) + }) + }) + } +``` + +#### Push new messages in the _buttonHandle function + +```javascript +_handleButton(event) { + this.messagesRef.push(this.refs.messageInput.value) +} +``` + +## Exercise 3 + Homework +Write a persistant chat app with React + Firebase. + +- Create a login page where the user enters their name +- Validate that the name is more than 1 character and show error otherwise +- Upon login show all previously written messages along with + - Username + - Message + - Time +- Let users enter new messages and show them in real time +- Read about firebase Authentication - https://www.firebase.com/docs/web/guide/user-auth.html +- Implement user authentication using email and password +- Style the app to your heart's content +- Deploy your app to firebase and send us a link in slack + diff --git a/lesson 999 - Next Steps.md b/lesson 999 - Next Steps.md new file mode 100644 index 0000000..6b978cb --- /dev/null +++ b/lesson 999 - Next Steps.md @@ -0,0 +1,42 @@ +## Next Steps + +# Next Steps + +### A list of resources for helping anyone on their coding journey + +## Tutorials and Books + +[Free Code Camp](https://www.freecodecamp.com/) - A 2000 hour course that takes you through each step of full-stack development (React material coming soon)
    +[React For Beginners](https://reactforbeginners.com/) - A famous intro to react from Wes Bos
    +[Code School's JS path](https://www.codeschool.com/learn/javascript) - An Excellent way to review and sharpen your JS skills
    +[ReactJS Fundamentals](http://www.reactjsprogram.com/) A project based, linear approach to learning React.js and the React.js ecosystem
    +[Egghead.io](https://egghead.io)- An excellent series of videos focusing on all things front-end.
    +[FrontEnd Masters](https://frontendmasters.com/) - Excellent lectures and examples of JS from beginner to advanced +[All of the TeamTreehouse JS videos](http://teamtreehouse.com/library/topic:javascript) - (you can add them to your dashboard and work through each independent of a track) +[NodeSchool.io](http://nodeschool.io/) - Though you're already familiar with it, NodeSchool is an excellent resource to continue sharpening your skills
    + + +## Challenges + +[Code Wars](http://www.codewars.com/) - is an excellent way to sharpen your skills. I try to spend at least 30 minutes a day working on problems.
    +[Code Combat](http://www.codecombat.com) - a fun and quirky way to work with basic JS or Python
    + + +##To get involved (and get noticed) + +[Trending on GitHub](https://github.com/trending) - a list of trending repos on GitHub
    +[Code for Charlotte](http://www.meetup.com/Code-For-Charlotte/) - you should already be involved here. +[Charlotte JS](http://www.meetup.com/CharlotteJS/) - hardcore JS with a great group of people +[Charlotte Front End Developers](http://www.meetup.com/Charlotte-Front-End-Developers/) - great topics concerning all things front-end + + +## Podcasts + +[JavaScript Air](http://javascriptair.com/) - RoundTable from many of the leading JS developers
    +[React Podcast](http://reactpodcast.com/) +[Code Newbie](http://www.codenewbie.org/podcast) - Awesome resource for new developers. (I’d recommend starting at the beginning) +[Reboot](http://rebootshow.fm/) - a Thoughtbot experiment that interviews people that transitioned from various careers into development +[Giant Robots Smashign into Other Robots](http://giantrobots.fm/) - Thoughtbot podcast dealing with dev, design, business, etc (usually has an interview) +[Developer Tea](https://developertea.com/) - short podcasts that deal with all various aspects of becoming a great developer +[The FrontSide](https://frontsidethepodcast.simplecast.fm/) - two guys talking about code and life +[Hansel Minutes](http://hanselminutes.com/) - Like NPR’s fresh air… just aimed at developers