tutorial.js 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141
  1. let Comment = React.createClass({
  2. rawMarkup: function () {
  3. let rawMarkup = marked(this.props.children.toString(), { sanitize: true });
  4. return { __html: rawMarkup };
  5. },
  6. render: function () {
  7. return (
  8. <div className="comment">
  9. <h2 className="commentAuthor">
  10. {this.props.author}
  11. </h2>
  12. <span dangerouslySetInnerHTML={this.rawMarkup()} />
  13. </div>
  14. );
  15. }
  16. });
  17. let CommentList = React.createClass({
  18. render: function () {
  19. let commentNodes = this.props.data.map(function (comment) {
  20. return (
  21. <Comment author={comment.author} key={comment.id}>
  22. {comment.text}
  23. </Comment>
  24. );
  25. });
  26. return (
  27. <div className="commentList">
  28. {commentNodes}
  29. </div>
  30. );
  31. }
  32. });
  33. let CommentForm = React.createClass({
  34. getInitialState: function () {
  35. return {
  36. author: "",
  37. text: ""
  38. };
  39. },
  40. handleAuthorChange: function (e) {
  41. this.setState({ author: e.target.value });
  42. },
  43. handleSubmit: function (e) {
  44. e.preventDefault();
  45. let author = this.state.author.trim();
  46. let text = this.state.text.trim();
  47. if (!text || !author) {
  48. return;
  49. }
  50. this.props.onCommentSubmit({ author: author, text: text });
  51. this.setState({ author: '', text: '' });
  52. },
  53. handleTextChange: function (e) {
  54. this.setState({ text: e.target.value });
  55. },
  56. render: function () {
  57. return (
  58. <div className="commentForm">
  59. <form className="commentForm" onSubmit={this.handleSubmit}>
  60. <input
  61. type="text"
  62. placeholder="Your name"
  63. value={this.state.author}
  64. onChange={this.handleAuthorChange}
  65. />
  66. <input
  67. type="text"
  68. placeholder="Say something..."
  69. value={this.state.text}
  70. onChange={this.handleTextChange}
  71. />
  72. <input type="submit" value="Post" />
  73. </form>
  74. </div>
  75. );
  76. }
  77. });
  78. let CommentBox = React.createClass({
  79. componentDidMount: function () {
  80. this.loadCommentsFromServer();
  81. setInterval(this.loadCommentsFromServer, this.props.pollInterval);
  82. },
  83. getInitialState: function () {
  84. return { data: [] };
  85. },
  86. handleCommentSubmit: function (comment) {
  87. let comments = this.state.data;
  88. // Optimistically set an id on the new comment. It will be replaced by an
  89. // id generated on the server. In a production application, you would likely
  90. // not use Date.now() for this and would have a more robust system in place.
  91. comment.id = Date.now();
  92. let newComments = comments.concat([comment]);
  93. // Assume all will go well.
  94. this.setState({ data: newComments });
  95. $.ajax({
  96. url: this.props.url,
  97. dataType: "json",
  98. type: "POST",
  99. data: comment,
  100. success: function (data) {
  101. this.setState({ data: data });
  102. }.bind(this),
  103. error: function (xhr, status, err) {
  104. // Restore the original comment state since the new state could not be applied.
  105. this.setState({data: comments });
  106. console.error(this.props.url, status, err.toString());
  107. }
  108. });
  109. },
  110. loadCommentsFromServer: function () {
  111. $.ajax({
  112. url: this.props.url,
  113. dataType: "json",
  114. cache: false,
  115. success: function (result) {
  116. this.setState({ data: result });
  117. }.bind(this),
  118. error: function (xhr, status, err) {
  119. console.error(this.props.url, status, err.toString());
  120. }.bind(this)
  121. });
  122. },
  123. render: function () {
  124. return (
  125. <div className="commentBox">
  126. <h1>Comments</h1>
  127. <CommentList data={this.state.data} />
  128. <CommentForm onCommentSubmit={this.handleCommentSubmit} />
  129. </div>
  130. );
  131. }
  132. });
  133. ReactDOM.render(
  134. <CommentBox url="/api/comments" pollInterval={2000} />,
  135. document.getElementById("content")
  136. );