Part 6: Managing State with Child Components
Profile.js
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 |
var React = require('react'); var Router = require('react-router'); var Repos = require('./Github/Repos.js'); var UserProfile = require('./Github/UserProfile.js'); var Notes = require('./Notes/Notes.js'); var ReactFireMixin = require('reactfire'); var Firebase = require('firebase'); var Profile = React.createClass({ mixins: [Router.State, ReactFireMixin], // Allows to query the route parameter and to get the specific username, also allows communication of react fire with firebase and the profile component getInitialState: function () { return { notes: ['noe1', 'note2'], bio: {name: 'Smilyan'}, repos: [1,2,3] } }, componentDidMount: function () { // Where all AJAX requests will live this.ref = new Firebase('https://react-git-profiler.firebaseio.com'); var childRef = this.ref.child(this.getParams().username); this.bindAsArray(childRef, 'notes'); // .bindAsArray is added as a property when we inserted "ReactFireMixin" into the mixins: array above }, componentWillUnmount: function () { // So that we don't get listeners keep adding, we will unmount them this.unbind('notes'); }, handleAddNote: function (newNote) { // Make the function in the component where it will be evoked this.ref.child(this.getParams().username).set(this.state.notes.concat([newNote])); // Get current profile and replace the data at the selected endpoint with the value in .set() // in .set() we get the previous values in an array and output a new array with newNote added }, render: function () { var username = this.getParams().username; // "username" is what we use in the route URL in routes.js return ( <div className="row"> <div className="col-md-4"> <UserProfile username={username} bio={this.state.bio} /> </div> <div className="col-md-4"> <Repos username={username} repos={this.state.repos} /> </div> <div className="col-md-4"> <Notes username={username} notes={this.state.notes} addNote={this.handleAddNote} /> </div> </div> ) } }); module.exports = Profile; |
Notes.js
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
var React = require('react'); var NotesList = require('./NotesList'); var AddNote = require('./AddNote'); var Notes = React.createClass({ propTypes: { username: React.PropTypes.string.isRequired, notes: React.PropTypes.array.isRequired, addNote: React.PropTypes.func.isRequired }, render: function () { return ( <div> <h3>Notes for {this.props.username}</h3> <AddNote username={this.props.username} addNote={this.props.addNote} /> <NotesList notes={this.props.notes} /> </div> ) } }); module.exports = Notes; |
NotesList.js
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
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}</li> }); return ( <ul className="list-group"> {notes} </ul> ) } }); module.exports = NotesList; |
AddNote.js
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
var React = require('react'); var AddNote = React.createClass({ propTypes: { username: React.PropTypes.string.isRequired, addNote: React.PropTypes.func.isRequired }, handleSubmit: function () { var newNote = this.refs.note.getDOMNode().value; // This is getting the value from the input below with a ref="note" this.refs.note.getDOMNode().value = ''; this.props.addNote(newNote); }, render: function () { return ( <div className="input-group"> <input type="text" className="form-control" ref="note" placeholder="Add New Note" /> <span className="input-group-btn"> <button type="submit" className="btn btn-default" onClick={this.handleSubmit}>Add Note</button> </span> </div> ) } }); module.exports = AddNote; |