Last active
June 8, 2016 18:27
-
-
Save stevenpollack/b066b13b6d4df41dd831795db72e89db to your computer and use it in GitHub Desktop.
React notes
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// React components must extend the React.Component Class | |
// and therefore expose a render method, which returns | |
// JSX (JavaScript XML). | |
// JSX looks exactly like unquoted HTML, except that | |
// - the HTML 'class' attribute is referenced via 'className' | |
// - we can mix in javascript via code blocks enclosed in {} | |
// - we can send arguments ('props' in React) to components: | |
// + props are accessed via the `this.props` object | |
// - we can access state with (`this.state`) | |
class Comment extends React.Component { | |
render () { | |
return( | |
<div className="comment"> | |
<p className="comment-header">{this.props.author}</p> | |
<p className="comment-body">{this.props.body}</p> | |
<div className="comment-footer"> | |
<a href="#" onClick={this._handleDelete.bind(this)} className="comment-footer-delete"> | |
Delete comment | |
</a> | |
</div> | |
</div> | |
); | |
} | |
_handleDelete(event) { | |
event.preventDefault(); | |
if (confirm('Are you sure?')) { | |
this.props.onDelete(this.props.comment); | |
} | |
} | |
} | |
// this now allows us to define a <Comment/> react component in our JSX and | |
// - pass props to it | |
// - change code according to state (we'll need a constructor to handle state defaults) | |
class CommentBox extends React.Component { | |
constructor() { | |
super(); // must be first line called in a constructor | |
this.state = { | |
showComments: false, | |
comments: [ ] // initialize this to something empty that we'll populate later | |
}; | |
} | |
render () { | |
const comments = this._getComments(); | |
let commentNodes; | |
let buttonText = 'Show comments'; | |
if (this.state.showComments) { | |
buttonText = 'Hide comments'; | |
commentNodes = <div className="comment-list">{comments}</div>; | |
} | |
return( | |
<button onClick={this._handleClick.bind(this)}>{buttonText}</button> | |
<div className="comment-box"> | |
<CommentForm addComment={this._addComment.bind(this)} /> | |
<h3>Comments</h3> | |
<h4 className="comment-count">{this._getCommentsTitle(comments.length)}</h4> | |
{commentNodes} | |
</div> | |
); | |
} | |
// this gets called BEFORE component is rendered | |
componentWillMount() { | |
_fetchComments(); | |
} | |
// this is called just AFTER component is rendered | |
componentDidMount() { | |
// poll the server every 5s... | |
// To avoid memory leaks, capture the timer and unmount it later | |
this._time = setInterval( | |
() => this._fetchComments(), | |
5000 | |
); | |
} | |
// this is called when component is ABOUT TO BE REMOVED | |
componentWillUnmount() { | |
clearInterval(this._timer); | |
} | |
// pass this to the <Comment /> to communicate results | |
_deleteComment(comment) { | |
someDeleteMethod(comment.id) // don't set up a callback or wait for confirmation of deletion | |
// remove the passed in comment, client-side | |
const comments = [...this.state.comments]; // use ...-operator and [] to clone array | |
const commentIndex = comments.indexOf(comment); | |
comments.splice(commentIndex, 1); | |
this.setSate({ comments }); // for a UI update | |
} | |
// calling this function in render() will create an infinite loop, since | |
// render is always called after this.setState() | |
_fetchComments() { | |
someGetRequest(comments => this.setState({ comments }) ) // could use jQuery.ajax or whatever to fetch the comments | |
} | |
_addComment(author, body) { // this is passed to and called from the <CommentForm /> | |
const comment = {author, body}; | |
makePostRequest(newcomment => { | |
// the successful post request should return an object with a unique key | |
// use concat instead of push to avoid mutating the comments array; it helps react stay fast | |
this.setState({ comments: this.state.comments.concat([comment]) }); | |
}) | |
} | |
_handleClick() { | |
// calling setState forces the component to re-render... | |
this.setState({ | |
showComments: !this.state.showComments // this will modify ONLY the showComments property | |
}); | |
} | |
_getCommentsTitle (commentCount) { | |
if (commentCount === 0) { | |
return 'No comments yet'; | |
} else if (commentCount === 1) { | |
return '1 comment'; | |
} else { | |
return `${commentCount} comments`; | |
} | |
} | |
_getComments () { // underscored functions distinguish custom vs. react methods | |
return this.state.comments.map((comment) => { | |
// good practice to pass in a unique value as a components key -- can help improve performance | |
return( | |
<Comment | |
author={comment.author} | |
body={comment.body} | |
key={comment.id} | |
onDelete={this._deleteComment.bind(this)} /> // bind the scope of _deleteComment to this environment | |
); | |
}); | |
} | |
} | |
// create a CommentForm component that demonstates _refs_: | |
// Refs allow us to reference DOM elements in our code, after the component has been rendered. | |
// NOTE: react runs the ref call backs on render() | |
class CommentForm extends React.Component { | |
render() { | |
return ( | |
<form className="comment-form" onSubmit={this._handleSubmit.bind(this)}> | |
<label>Join the discussion</label> | |
<div className="comment-form-fields"> | |
<input placeholder="Name:" ref={(input) => this._author = input}/> | |
<textarea placeholder="Comment:" ref={(textarea) => this._body = textarea}> | |
</textarea> | |
</div> | |
<div className="comment-form-actions"> | |
<button type="submit"> | |
Post comment | |
</button> | |
</div> | |
</form> | |
); | |
} | |
_handleSubmit(event) { | |
event.preventDefault(); // prevent page from reloading, when form is submitted. | |
// grab information populated from refs in JSX | |
let author = this._author; | |
let body = this._body; | |
this.props.addComment(author.value, body.value); // this method has been passed as an argument to <CommentForm/> | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Check out the list of React synthetic events (e.g.
onSubmit
oronClick
)...