├── .gitignore
├── README.md
├── css
└── base.css
├── index.html
├── package.json
├── scripts
├── CommentBox.jsx
└── example.jsx
├── server.js
└── webpack.config.js
/.gitignore:
--------------------------------------------------------------------------------
1 | *~
2 | node_modules
3 | .DS_Store
4 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # OUT OF DATE
2 |
3 | **This example is no longer maintained. Check out [React Hot Loader starter kits](https://github.com/gaearon/react-hot-loader/tree/master/docs#starter-kits) instead. For the most minimal example, see [React Hot Boilerplate](https://github.com/gaearon/react-hot-boilerplate).**
4 |
5 |
6 | # About this fork
7 |
8 | This is a fork of react-tutorial that supports live editing via **[react-hot-loader](https://github.com/gaearon/react-hot-loader)**.
9 | This means you can edit `CommentBox.jsx` after running the server, and it will update without reload.
10 |
11 | --------------------
12 |
13 | # React comment box example
14 |
15 | This is the React comment box example from [the React tutorial](http://facebook.github.io/react/docs/tutorial.html).
16 |
17 | ## To use
18 |
19 | ```
20 | npm install
21 | node server.js
22 | ```
23 |
24 | And visit http://localhost:3000/. Try opening multiple tabs!
25 |
--------------------------------------------------------------------------------
/css/base.css:
--------------------------------------------------------------------------------
1 | body {
2 | background: #fff;
3 | font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;;
4 | font-size: 15px;
5 | line-height: 1.7;
6 | margin: 0;
7 | padding: 30px;
8 | }
9 |
10 | a {
11 | color: #4183c4;
12 | text-decoration: none;
13 | }
14 |
15 | a:hover {
16 | text-decoration: underline;
17 | }
18 |
19 | code {
20 | background-color: #f8f8f8;
21 | border: 1px solid #ddd;
22 | border-radius: 3px;
23 | font-family: "Bitstream Vera Sans Mono", Consolas, Courier, monospace;
24 | font-size: 12px;
25 | margin: 0 2px;
26 | padding: 0px 5px;
27 | }
28 |
29 | h1, h2, h3, h4 {
30 | font-weight: bold;
31 | margin: 0 0 15px;
32 | padding: 0;
33 | }
34 |
35 | h1 {
36 | border-bottom: 1px solid #ddd;
37 | font-size: 2.5em;
38 | font-weight: bold;
39 | margin: 0 0 15px;
40 | padding: 0;
41 | }
42 |
43 | h2 {
44 | border-bottom: 1px solid #eee;
45 | font-size: 2em;
46 | }
47 |
48 | h3 {
49 | font-size: 1.5em;
50 | }
51 |
52 | h4 {
53 | font-size: 1.2em;
54 | }
55 |
56 | p, ul {
57 | margin: 15px 0;
58 | }
59 |
60 | ul {
61 | padding-left: 30px;
62 | }
63 |
--------------------------------------------------------------------------------
/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Hello React
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "react-tutorial",
3 | "version": "0.0.0",
4 | "description": "Code from the React tutorial.",
5 | "main": "server.js",
6 | "dependencies": {
7 | "body-parser": "^1.6.6",
8 | "cors": "^2.4.1",
9 | "express": "^4.8.6",
10 | "jquery": "^1.11.1",
11 | "react": "^0.11.0"
12 | },
13 | "devDependencies": {
14 | "jsx-loader": "^0.11.0",
15 | "react-hot-loader": "^0.4.2",
16 | "webpack": "^1.4.0-beta1",
17 | "webpack-dev-server": "^1.5.0"
18 | },
19 | "scripts": {
20 | "test": "echo \"Error: no test specified\" && exit 1",
21 | "start": "node server.js"
22 | },
23 | "repository": {
24 | "type": "git",
25 | "url": "https://github.com/reactjs/react-tutorial.git"
26 | },
27 | "keywords": [
28 | "react",
29 | "tutorial",
30 | "comment",
31 | "example"
32 | ],
33 | "author": "petehunt",
34 | "license": "MIT",
35 | "bugs": {
36 | "url": "https://github.com/reactjs/react-tutorial/issues"
37 | },
38 | "homepage": "https://github.com/reactjs/react-tutorial"
39 | }
40 |
--------------------------------------------------------------------------------
/scripts/CommentBox.jsx:
--------------------------------------------------------------------------------
1 | /** @jsx React.DOM */
2 |
3 | var Showdown = require('showdown'),
4 | $ = require('jquery'),
5 | React = require('react'),
6 | converter = new Showdown.converter();
7 |
8 | var Comment = React.createClass({
9 | render: function() {
10 | var rawMarkup = converter.makeHtml(this.props.children.toString());
11 | return (
12 |
13 |
14 | {this.props.author}
15 |
16 |
17 |
18 | );
19 | }
20 | });
21 |
22 | var CommentBox = React.createClass({
23 | loadCommentsFromServer: function() {
24 | $.ajax({
25 | url: this.props.url,
26 | dataType: 'json',
27 | success: function(data) {
28 | this.setState({data: data});
29 | }.bind(this),
30 | error: function(xhr, status, err) {
31 | console.error(this.props.url, status, err.toString());
32 | }.bind(this)
33 | });
34 | },
35 | handleCommentSubmit: function(comment) {
36 | var comments = this.state.data;
37 | comments.push(comment);
38 | this.setState({data: comments}, function() {
39 | // `setState` accepts a callback. To avoid (improbable) race condition,
40 | // `we'll send the ajax request right after we optimistically set the new
41 | // `state.
42 | $.ajax({
43 | url: this.props.url,
44 | dataType: 'json',
45 | type: 'POST',
46 | data: comment,
47 | success: function(data) {
48 | this.setState({data: data});
49 | }.bind(this),
50 | error: function(xhr, status, err) {
51 | console.error(this.props.url, status, err.toString());
52 | }.bind(this)
53 | });
54 | });
55 | },
56 | getInitialState: function() {
57 | return {data: []};
58 | },
59 | componentDidMount: function() {
60 | this.loadCommentsFromServer();
61 | setInterval(this.loadCommentsFromServer, this.props.pollInterval);
62 | },
63 | render: function() {
64 | return (
65 |
66 |
Comments
67 |
68 |
69 |
70 | );
71 | }
72 | });
73 |
74 | var CommentList = React.createClass({
75 | render: function() {
76 | var commentNodes = this.props.data.map(function(comment, index) {
77 | return (
78 | // `key` is a React-specific concept and is not mandatory for the
79 | // purpose of this tutorial. if you're curious, see more here:
80 | // http://facebook.github.io/react/docs/multiple-components.html#dynamic-children
81 |
82 | {comment.text}
83 |
84 | );
85 | });
86 | return (
87 |
88 | {commentNodes}
89 |
90 | );
91 | }
92 | });
93 |
94 | var CommentForm = React.createClass({
95 | handleSubmit: function(e) {
96 | e.preventDefault();
97 | var author = this.refs.author.getDOMNode().value.trim();
98 | var text = this.refs.text.getDOMNode().value.trim();
99 | if (!text || !author) {
100 | return;
101 | }
102 | this.props.onCommentSubmit({author: author, text: text});
103 | this.refs.author.getDOMNode().value = '';
104 | this.refs.text.getDOMNode().value = '';
105 | return;
106 | },
107 | render: function() {
108 | return (
109 |
114 | );
115 | }
116 | });
117 |
118 | module.exports = CommentBox;
--------------------------------------------------------------------------------
/scripts/example.jsx:
--------------------------------------------------------------------------------
1 | /** @jsx React.DOM */
2 |
3 | var CommentBox = require('./CommentBox'),
4 | React = require('react');
5 |
6 | React.renderComponent(
7 | ,
8 | document.getElementById('content')
9 | );
10 |
--------------------------------------------------------------------------------
/server.js:
--------------------------------------------------------------------------------
1 | var express = require('express');
2 | var bodyParser = require('body-parser');
3 | var app = express();
4 | var webpack = require('webpack');
5 | var WebpackDevServer = require('webpack-dev-server');
6 | var config = require('./webpack.config');
7 | var cors = require('cors');
8 |
9 | var comments = [{author: 'Pete Hunt', text: 'Hey there!'},
10 | {author: 'Justin Gordon', text: 'Aloha from @railsonmaui'}
11 | ];
12 |
13 | app.use(bodyParser.json());
14 | app.use(bodyParser.urlencoded({extended: true}));
15 | app.use(cors());
16 |
17 | app.get('/comments.json', function(req, res) {
18 | res.setHeader('Content-Type', 'application/json');
19 | res.send(JSON.stringify(comments));
20 | });
21 |
22 | app.post('/comments.json', function(req, res) {
23 | comments.push(req.body);
24 | res.setHeader('Content-Type', 'application/json');
25 | res.send(JSON.stringify(comments));
26 | });
27 |
28 | app.listen(3001);
29 |
30 | new WebpackDevServer(webpack(config), {
31 | publicPath: config.output.publicPath,
32 | hot: true
33 | }).listen(3000, 'localhost', function (err, result) {
34 | if (err) {
35 | console.log(err);
36 | }
37 |
38 | console.log('Listening at localhost:3000');
39 | });
40 |
--------------------------------------------------------------------------------
/webpack.config.js:
--------------------------------------------------------------------------------
1 | var webpack = require('webpack');
2 |
3 | module.exports = {
4 | entry: [
5 | 'webpack-dev-server/client?http://localhost:3000',
6 | 'webpack/hot/dev-server',
7 | './scripts/example'
8 | ],
9 | output: {
10 | path: __dirname,
11 | filename: 'bundle.js',
12 | publicPath: '/scripts/'
13 | },
14 | plugins: [
15 | new webpack.HotModuleReplacementPlugin()
16 | ],
17 | resolve: {
18 | extensions: ['', '.js', '.jsx']
19 | },
20 | module: {
21 | loaders: [
22 | { test: /\.jsx$/, loaders: ['react-hot', 'jsx'] },
23 | ]
24 | },
25 | externals: {
26 | 'showdown': 'window.Showdown'
27 | }
28 | };
--------------------------------------------------------------------------------