<html>
<head>
<meta name="description" content="React with List of Comments">
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/0.13.3/react.js"></script>
<script src="https://rawgit.com/spoike/refluxjs/master/dist/reflux.js"></script>
<meta charset="utf-8">
<title>JS Bin</title>
</head>
<body>
<div id="example"></div>
</body>
</html>
const commentActions = Reflux.createActions({
addComment: {}
});
const commentStore = Reflux.createStore({
data: {
comments: [{
id: 1,
author: 'Bob Dobson',
text: 'I had a great time'
},{
id: 2,
author: 'John Thompson',
text: 'It was the worst day of my life'
},{
id: 3,
author: 'Stan Simpson',
text: 'Meh'
}]
},
getInitialState() {
this.data.newComment = this.getDefaultComment();
return this.data;
},
init() {
this.listenTo(commentActions.addComment, this.addComment);
},
getDefaultComment() {
return {
text: '',
author: ''
};
},
addComment(newComment) {
newComment.id = this.data.comments.length + 1;
this.data.comments = this.data.comments.concat([newComment]);
this.data.newComment = this.getDefaultComment();
this.trigger(this.data);
}
});
class Comment extends React.Component {
render() {
return (
<div className="comment">
<p>{this.props.comment.text}</p>
<p>by <strong>{this.props.comment.author}</strong></p>
</div>
)
}
}
Comment.propTypes = {
comment: React.PropTypes.shape({
text: React.PropTypes.string.isRequired,
author: React.PropTypes.string.isRequired
})
};
class CommentList extends React.Component {
render() {
return (
<div className="comment-list">
{this.props.comments.map(comment => <Comment comment={comment} key={comment.id} />)}
</div>
)
}
}
CommentList.propTypes = {
comments: React.PropTypes.array.isRequired
};
class CommentForm extends React.Component {
handleSubmit(e) {
e.preventDefault();
this.props.onSubmit(this.props.comment);
}
render() {
return (
<form onSubmit={this.handleSubmit.bind(this)}>
<div>
<textarea placeholder="Your Comment" rows="4" cols="40" value={this.props.comment.text} name="text" onChange={this.props.onChange} />
</div>
<div>
<input type="text" placeholder="Your Name" value={this.props.comment.author} name="author" onChange={this.props.onChange} />
</div>
<button type="submit">Add Comment</button>
</form>
)
}
}
CommentForm.propTypes = {
onSubmit: React.PropTypes.func.isRequired,
onChange: React.PropTypes.func.isRequired,
comment: React.PropTypes.shape({
text: React.PropTypes.string.isRequired,
author: React.PropTypes.string.isRequired
}).isRequired
};
class CommentsContainer extends React.Component {
constructor(props) {
super(props);
this.state = commentStore.getInitialState();
}
componentDidMount() {
commentStore.listen(this.onCommentsChange.bind(this));
}
onCommentsChange(data) {
this.setState(data);
}
handleChange(name, value) {
let newComment = { this.state.newComment };
newComment[name] = value;
this.setState({
newComment: newComment
});
}
handleSubmit(newComment) {
commentActions.addComment(newComment);
}
render() {
return (
<div className="comments-container">
<CommentList comments={this.state.comments} />
<CommentForm
comment={this.state.newComment}
onSubmit={newComment => this.handleSubmit(newComment)}
onChange={e => this.handleChange(e.target.name, e.target.value)} />
</div>
)
}
}
React.render(
<CommentsContainer />,
document.getElementById('example')
);
Output
You can jump to the latest bin by adding /latest
to your URL
Keyboard Shortcuts
Shortcut | Action |
---|---|
ctrl + [num] | Toggle nth panel |
ctrl + 0 | Close focused panel |
ctrl + enter | Re-render output. If console visible: run JS in console |
Ctrl + l | Clear the console |
ctrl + / | Toggle comment on selected lines |
ctrl + ] | Indents selected lines |
ctrl + [ | Unindents selected lines |
tab | Code complete & Emmet expand |
ctrl + shift + L | Beautify code in active panel |
ctrl + s | Save & lock current Bin from further changes |
ctrl + shift + s | Open the share options |
ctrl + y | Archive Bin |
Complete list of JS Bin shortcuts |
JS Bin URLs
URL | Action |
---|---|
/ | Show the full rendered output. This content will update in real time as it's updated from the /edit url. |
/edit | Edit the current bin |
/watch | Follow a Code Casting session |
/embed | Create an embeddable version of the bin |
/latest | Load the very latest bin (/latest goes in place of the revision) |
/[username]/last | View the last edited bin for this user |
/[username]/last/edit | Edit the last edited bin for this user |
/[username]/last/watch | Follow the Code Casting session for the latest bin for this user |
/quiet | Remove analytics and edit button from rendered output |
.js | Load only the JavaScript for a bin |
.css | Load only the CSS for a bin |
Except for username prefixed urls, the url may start with http://jsbin.com/abc and the url fragments can be added to the url to view it differently. |