diff --git a/React/comments.js b/React/comments.js
new file mode 100644
index 000000000..50389032f
--- /dev/null
+++ b/React/comments.js
@@ -0,0 +1,152 @@
+import React from 'react';
+import ReactDOM from 'react-dom';
+//imagine that we receive some data from db
+
+let data = [
+ {id: 1, author: "Peter", text: "Hello"},
+ {id: 2, author: "Ivan", text: "Hi"}
+];
+
+let CommentBox = React.createClass({
+ loadCommentsFromServer: function() {
+ $.ajax({
+ url: this.props.url,
+ dataType: 'json',
+ cache: false,
+ success: function(data) {
+ this.setState({data: data});
+ }.bind(this),
+ error: function(xhr, status, err) {
+ console.error(this.props.url, status, err.toString());
+ }.bind(this)
+ });
+ },
+
+ handleCommentSubmit: function(comment) {
+ let comments = this.state.data;
+comment.id = Date.now();
+let newComments = comments.concat([comment]);
+this.setState({data: newComments});
+ $.ajax({
+ url: this.props.url,
+ dataType: 'json',
+ type: 'POST',
+ data: comment,
+ success: function(data) {
+ this.setState({data: data});
+ }.bind(this),
+ error: function(xhr, status, err) {
+ console.error(this.props.url, status, err.toString());
+ }.bind(this)
+ });
+ },
+
+ getInitialState: function() {
+ return {data: []};
+ },
+
+ componentDidMount: function() {
+ this.loadCommentsFromServer();
+ setInterval(this.loadCommentsFromServer, this.props.pollInterval);
+ },
+
+ render: function() {
+ return (
+
+
Comments
+
+
+
+ );
+ }
+});
+ReactDOM.render(
+//,
+,
+ document.getElementById('content')
+);
+
+let CommentList = React.createClass({
+ render: function() {
+
+ let commentNodes = this.props.data.map(function(comment) {
+ return (
+
+ {comment.text}
+
+ );
+ });
+
+ return (
+
+ This is one comment
+ This is *another* comment
+
+ );
+ }
+});
+
+let CommentForm = React.createClass({
+ getInitialState: function() {
+ return {author: '', text: ''};
+ },
+ handleAuthorChange: function(e) {
+ this.setState({author: e.target.value});
+ },
+ handleTextChange: function(e) {
+ this.setState({text: e.target.value});
+ },
+
+ handleSubmit: function(e) {
+ e.preventDefault();
+ var author = this.state.author.trim();
+ var text = this.state.text.trim();
+ if (!text || !author) {
+ return;
+ }
+ this.props.onCommentSubmit({author: author, text: text});
+ this.setState({author: '', text: ''});
+
+ },
+
+ render: function() {
+ return (
+
+ );
+ }
+});
+
+let Comment = React.createClass({
+ rawMarkup: function() {
+ var rawMarkup = marked(this.props.children.toString(), {sanitize: true});
+ return { __html: rawMarkup };
+},
+
+ render: function() {
+ return (
+
+
+ {this.props.author}
+
+ //if we want to add markdown
+ //first add marked library
+ //
+ {this.props.children}
+
+ );
+ }
+});
diff --git a/React/comments.json b/React/comments.json
new file mode 100644
index 000000000..fcae6963f
--- /dev/null
+++ b/React/comments.json
@@ -0,0 +1,27 @@
+
+ {
+ "id": 1388534400000,
+ "author": "Petrenko",
+ "text": "Hey there!"
+ },
+ {
+ "id": 1420070400000,
+ "author": "Symonenko",
+ "text": "React is *great*!"
+ },
+ {
+ "id": 1464988635157,
+ "author": "Ivanov",
+ "text": "*abc*"
+ },
+ {
+ "id": 1464988636500,
+ "author": "Grushevskii",
+ "text": "*abc*"
+ },
+ {
+ "id": 1464988717637,
+ "author": "Jobs",
+ "text": "alert(1)"
+ }
+]