Skip to content

Instantly share code, notes, and snippets.

@jendiamond
Last active February 16, 2016 20:46
Show Gist options
  • Select an option

  • Save jendiamond/30c0c5c0ff7116e1b051 to your computer and use it in GitHub Desktop.

Select an option

Save jendiamond/30c0c5c0ff7116e1b051 to your computer and use it in GitHub Desktop.

$ source nodeenv/bin/activate

1 - 6

$ npm init

$ npm install [email protected]

$ ls

$ npm install [email protected]

$ npm install --save- dev [email protected] [email protected] [email protected] [email protected]

$ mkdir public

$ touch index.html

$ npm install webpack -g

$ touch webpack.config.js


webpack.config.js

module.exports = {
  entry: "./app/components/Main.js",
  output: {
    filename: "public/bundle.js"
  },
  module: {
    loaders: [
      {
        test: /\.jsx?$/,
        exclude: /(node_modules|bower_components)/,
        loader: 'babel',
        query: {
          presets:['react', 'es2015']
        }
      }
    ]
  }
}

Main.js

$ mkdir app

$ mkdir components

$ touch Main.js

components/Main.js

var React = require('react');
var ReactDOM = require('react-dom');

var Main = React.createClass({
  render: function(){
    return (
      <div>
        Hello World
      </div>
    )
  }
});

ReactDOM.render(<Main />, document.getElemenById('app))

$ webpack -w

open index.html in the browser


Home.js

components/Home.js

var React = require('react');

var Home = React.createClass({
  render: function(){
    return (
      <h2 className="text-center">
        Search by Github Username Above
      </h2>
    )
  }
  });

To use bootstrap classes you need to use className instead of class.


ReactRouter

we don't want our main controller to be in charge of rendering our component.

  • Delete ReactDOM.render(<Main />, document.getElemenById('app)) from Main.js
  • Replace it with: module.export = Main;
    So when we require Main we get this component.
    Main.js no longer will be rendering the app so we can also
  • Delete var React = require('react');

components/Main.js

var ReactDOM = require('react-dom');

var Main = React.createClass({
  render: function(){
    return (
      <div>
        Hello World
      </div>
    )
  }
});

module.export = Main;

Create another component to be in charge of the routing

app/App.js

var React = require('react');
var ReactDOM = require('react-dom');
var Router = require('react-router').Router;
var routes = require('./config/routes');

$ npm install --save [email protected] [email protected]

app/App.js

var React = require('react');
var ReactDOM = require('react-dom');
var Router = require('react-router').Router;
var routes = require('./config/routes');

ReactDOM.render(
  <Router>{routes}</Router>,
  document.getElementById('app')
)

routes will be an instruction sheet to Router to decide which component to render based on which route we are at.


Change webpack.config.js to:

webpack.config.js

module.exports = {
  entry: "./app/App.js",
  output: {
    filename: "public/bundle.js"
  },
  module: {
    loaders: [
      {
        test: /\.jsx?$/,
        exclude: /(node_modules|bower_components)/,
        loader: 'babel',
        query: {
          presets:['react', 'es2015']
        }
      }
    ]
  }
}

routes

$ mkdir app/config

$ touch app/config/routes.js

When anyone goes to the root path they will be served the Main component.
Exporting the instructions for our router which with go to App.js. The Router receives those routes, goes to the Main component to see what to render.

app/config/routes.js

var React = require('react');
var Main = require('../components/Main');
var Home = require('../components/Home');
var Router = require('react-router');
var Route = Router.Route;

module.exports = (
  <Route path="/" component={Main}>
  </Route>
);

$ webpack -w


Make the Menu always be an active route and render some child components

app/config/routes.js

var React = require('react');
var Main = require('../components/Main');
var Home = require('../components/Home');
var Router = require('react-router');
var Route = Router.Route;
var IndexRoute = Router.IndexRoute;

module.exports = (
  <Route path="/" component={Main}>
    <IndexRoute component={Home} />
  </Route>
);

===

components/Main.js

var ReactDOM = require('react-dom');

var Main = React.createClass({
  render: function(){
    return (
      <div className="main-container">
        <nav className="navbar navbar-default" role="navigation">
          <div className="col-sm-7 col-sm-offset-2" style={{marginTop: 15}}>
            MENU
          </div>
        </nav>
        <div className="main-container">
          {this.props.children}
        </div>
      </div>
    )
  }
});

module.export = Main;

Profile Component & 3 Child Components

$ `touch components/Profile.js'

components/Profile.js

var ReactDOM = require('react-dom');
var Router = require('react-router');

var Profile = React.createClass({
  getInitialState: function(){
    return {
      notes: [],
      bios: {},
      repos: []
    }
  },
  render: function(){
    return (
      <div className="row">
        <div className="col-md-4">
          User Profile Component
        </div>
        <div className="col-md-4">
          Repos Component
        </div>
        <div className="col-md-4">
          Notes Component
        </div>
      </div>
    )
  }
});

module.exports = Profile;

Add profile component to routes

app/config/routes.js

var React = require('react');
var Main = require('../components/Main');
var Home = require('../components/Home');
var Profile = require('../components/Profile');
var Router = require('react-router');
var Route = Router.Route;
var IndexRoute = Router.IndexRoute;

module.exports = (
  <Route path="/" component={Main}>
    <Route path="profile/:username" component{Profile} />
    <IndexRoute component={Home} />
  </Route>
);

(react router path history)


Get UserNmae that we pass into our URL to our Profile container

Passing Props to a Component

How do we query our userName? params

components/Profile.js

var ReactDOM = require('react-dom');
var Router = require('react-router');

var Profile = React.createClass({
  getInitialState: function(){
    return {
      notes: [],
      bios: {},
      repos: []
    }
  },
  render: function(){
    return (
      <div className="row">
        <div className="col-md-4">
          User Profile Component --> {this.props.params.username}
        </div>
        <div className="col-md-4">
          Repos Component
        </div>
        <div className="col-md-4">
          Notes Component
        </div>
      </div>
    )
  }
});

module.exports = Profile;

this "username":
User Profile Component --> {this.props.params.username}
comes from: <Route path="profile/:username" component{Profile} />
in the app/config/routes.js

{displays JSX}


More Components

$ touch components/Github/Repos.js
$ touch components/Github/UserProfile.js
$ touch components/Notes/Notes.js

components/Github/Repos.js

var ReactDOM = require('react-dom');

var Repos = React.createClass({
  render: function(){
    return (
      <div>REPOS</div>
    )
  }
});

module.exports = Repos;

components/Github/UserProfile.js

var ReactDOM = require('react-dom');

var UserProfiles = React.createClass({
  render: function(){
    return (
      <div>USER PROFILES</div>
    )
  }
});

module.exports = UserProfile;

components/Notes/Notes.js

var ReactDOM = require('react-dom');

var Notes = React.createClass({
  render: function(){
    return (
      <div>NOTES</div>
    )
  }
});

module.exports = Notes;

===

components/Profile.js

var ReactDOM = require('react-dom');
var Router = require('react-router');
var Repos = require('./Github/Repos');
var UserProfile = require('./Github/UserProfile');
var Notes = require('./Notes/Notes');

var Profile = React.createClass({
  getInitialState: function(){
    return {
      notes: [1,2,3],
      bios: {
        name: 'Jen Diamond'
      },
      repos: ['a', 'b', 'c']
    }
  },
  render: function(){
    return (
      <div className="row">
        <div className="col-md-4">
          <UserProfile username={this.props.params.username} bio={this.state.bio} />
        </div>
        <div className="col-md-4">
          <Repos repos={this.state.repos} />
        </div>
        <div className="col-md-4">
          <Notes notes={this.state.notes} />
        </div>
      </div>
    )
  }
});

module.exports = Profile;

===

components/Github/UserProfile.js

var React = require('react');

var UserProfiles = React.createClass({
  render: function(){
    return (
      <div>
        <p>USER PROFILE</p>
        <p>User Name: {this.props.username}</p>
        <p>Bio: {this.props.bio.name}</p>
      </div>
    )
  }
});

module.exports = UserProfile;

components/Github/Repos.js

var React = require('react');

var Repos = React.createClass({
  render: function(){
    return (
      <div>
        <p>REPOS</p>
        <p>REPOS: {this.props.repos}</p>
      </div>
    )
  }
});

module.exports = Repos;

components/Notes/Notes.js

var React = require('react');

var Notes = React.createClass({
  render: function(){
    return (
      <div>
        <p>NOTES</p>
        <p>{this.props.notes}</p>
      </div>
    )
  }
});

module.exports = Notes;

Firebase

React Fire - binds a component state to a Firebase endpoint - which will give us auto updating

$ npm install --save [email protected]

$ npm install --save-dev webpack

$ npm install --save [email protected]

===

Add Firebase Mixins

Create a new instance of Firebase and pass it the URL of where our project is located. Returns an object of Firebase properties.

bindAsArray takes 2 arguments (reference to your Firebase, property on your state that you want to bind the Firebase data to)

components/Profile.js

var ReactDOM = require('react-dom');
var Router = require('react-router');
var Repos = require('./Github/Repos');
var UserProfile = require('./Github/UserProfile');
var Notes = require('./Notes/Notes');
var ReactFireMixin = require('reactfire');
var Firebase = require('firebase');

var Profile = React.createClass({
  mixins: [ReactFireMixin],
  getInitialState: function(){
    return {
      notes: [1,2,3],
      bios: {
        name: 'Jen Diamond'
      },
      repos: ['a', 'b', 'c']
    }
  },
  componentDidMount: function(){
    this.ref = new Firebase('https://github-note-taker.firebaseio.com/');
    var childRef = this.ref.child(this.props.params.username);
    this.bindAsArray(ChildRef, 'notes');
  },
  componentWillUnmount: function(){
    this.unbind('notes');
  },
  render: function(){
    return (
      <div className="row">
        <div className="col-md-4">
          <UserProfile username={this.props.params.username} bio={this.state.bio} />
        </div>
        <div className="col-md-4">
          <Repos username={this.props.params.username} repos={this.state.repos} />
        </div>
        <div className="col-md-4">
          <Notes username={this.props.params.username} notes={this.state.notes} />
        </div>
      </div>
    )
  }
});

module.exports = Profile;

===

components/Notes/Notes.js

var React = require('react');

var Notes = React.createClass({
  render: function(){
    console.log('Notes: ', this.props.notes)
    return (
      <div>
        <p>NOTES</p>
      </div>
    )
  }
});

module.exports = Notes;

$ webpack -w

look at inspect element Console

components/Notes/Notes.js

var React = require('react');

var Notes = React.createClass({
  render: function(){
    console.log('Notes: ', this.props.notes)
    return (
      <div>
        <h3>Notes for {this.props.username}</h3>
      </div>
    )
  }
});

module.exports = Notes;

Make a component that takes in an Array of items, Loops over those items and creates an unordered list.

$ touch components/Notes/NotesList.js

components/Notes/NotesList.js

var React = require('react');

var NotesList = React.createClass({
  render: function(){
    var notes = this.props.notes.map(function(note, index){
      return <li className="list-group-item" key={index}>{note['.value']}</li>
    })
    return (
      <ul className="list-group">
        {notes}
      </ul>
    )
  }
});

module.exports = NotesList;

===

components/Notes/Notes.js

var React = require('react');
var NotesList = require('./NotesList');

var Notes = React.createClass({
  render: function(){
    return (
      <div>
        <h3>Notes for {this.props.username}</h3>
        <NotesList notes={this.props.notes} />
      </div>
    )
  }
});

module.exports = Notes;

##6

Proptypes

propType validation

components/Github/Repos.js

var React = require('react');

var Repos = React.createClass({
  propTypes: {
    username: React.PropTypes.string.isRequired,
    repos: React.PropTypes.array.isRequired
  },
  render: function(){
    return (
      <div>
        <p>REPOS</p>
        <p>REPOS: {this.props.repos}</p>
      </div>
    )
  }
});

module.exports = Repos;

===

components/Github/UserProfile.js

var React = require('react');

var UserProfiles = React.createClass({
  propTypes: {
    username: React.PropTypes.string.isRequired,
    bio: React.PropTypes.object.isRequired
  },
  render: function(){
    return (
      <div>
        <p>USER PROFILE</p>
        <p>User Name: {this.props.username}</p>
        <p>Bio: {this.props.bio.name}</p>
      </div>
    )
  }
});

module.exports = UserProfile;

===

components/Notes/Notes.js

var React = require('react');
var NotesList = require('./NotesList');

var Notes = React.createClass({
  propTypes: {
    username: React.PropTypes.string.isRequired,
    notes: React.PropTypes.array.isRequired
  },
  render: function(){
    return (
      <div>
        <h3>Notes for {this.props.username}</h3>
        <NotesList notes={this.props.notes} />
      </div>
    )
  }
});

module.exports = Notes;

7 - 12

Write a function inside of the Profiles componenet and pass that function down to our child component and evoke it.

Whenever we update : var childRef = this.ref.child(this.props.params.username); those changes will automatically be pushed through to our state. It will update firebase, the component will re-render.

We are going to call .set which whatever we pass in is going to replace the data at this location or if there is no data there it will set the data.

  handleAddNote: function(newNote){
  this.ref.child(this.props.params.username).child(this.state.notes.length).set(newNote)
},
  • When the handleAddNote function is called it is going to be given a newNote
  • then we'll go to the url this.ref.child/username_jendiamond/items_in_the_array/(setting a new note there)/`
  • then set(newNote) appends the newNote onto the end of the firebase
  • and bindAsArray receives new data and pushes through to our notes state and updates the view.

components/Profile.js

var ReactDOM = require('react-dom');
var Router = require('react-router');
var Repos = require('./Github/Repos');
var UserProfile = require('./Github/UserProfile');
var Notes = require('./Notes/Notes');
var ReactFireMixin = require('reactfire');
var Firebase = require('firebase');

var Profile = React.createClass({
  mixins: [ReactFireMixin],
  getInitialState: function(){
    return {
      notes: [1,2,3],
      bios: {
        name: 'Jen Diamond'
      },
      repos: ['a', 'b', 'c']
    }
  },
  componentDidMount: function(){
    this.ref = new Firebase('https://github-note-taker.firebaseio.com/');
    var childRef = this.ref.child(this.props.params.username);
    this.bindAsArray(ChildRef, 'notes');
  },
  componentWillUnmount: function(){
    this.unbind('notes');
  },
  handleAddNote: function(newNote){
  this.ref.child(this.props.params.username).child(this.state.notes.length).set(newNote)
},
  render: function(){
    return (
      <div className="row">
        <div className="col-md-4">
          <UserProfile username={this.props.params.username} bio={this.state.bio} />
        </div>
        <div className="col-md-4">
          <Repos username={this.props.params.username} repos={this.state.repos} />
        </div>
        <div className="col-md-4">
          <Notes username={this.props.params.username} notes={this.state.notes} />
        </div>
      </div>
    )
  }
});

module.exports = Profile;

===

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment