diff --git a/.gitignore b/.gitignore new file mode 100644 index 00000000..daeba5f9 --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ +*~ +node_modules +.DS_Store diff --git a/README.md b/README.md new file mode 100644 index 00000000..a0001786 --- /dev/null +++ b/README.md @@ -0,0 +1,12 @@ +# React comment box example + +This is the React comment box example from [the React tutorial](http://facebook.github.io/react/docs/tutorial.html). + +## To use + +``` +npm install express +node server.js +``` + +And visit http://localhost:3000/. Try opening multiple tabs! diff --git a/css/base.css b/css/base.css new file mode 100755 index 00000000..3ed9ea38 --- /dev/null +++ b/css/base.css @@ -0,0 +1,62 @@ +body { + background: #fff; + font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;; + font-size: 15px; + line-height: 1.7; + margin: 0; + padding: 30px; +} + +a { + color: #4183c4; + text-decoration: none; +} + +a:hover { + text-decoration: underline; +} + +code { + background-color: #f8f8f8; + border: 1px solid #ddd; + border-radius: 3px; + font-family: "Bitstream Vera Sans Mono", Consolas, Courier, monospace; + font-size: 12px; + margin: 0 2px; + padding: 0px 5px; +} + +h1, h2, h3, h4 { + font-weight: bold; + margin: 0 0 15px; + padding: 0; +} + +h1 { + border-bottom: 1px solid #ddd; + font-size: 2.5em; + font-weight: bold; + margin: 0 0 15px; + padding: 0; +} + +h2 { + border-bottom: 1px solid #eee; + font-size: 2em; +} + +h3 { + font-size: 1.5em; +} + +h4 { + font-size: 1.2em; +} + +p, ul { + margin: 15px 0; +} + +ul { + padding-left: 30px; +} diff --git a/index.html b/index.html new file mode 100755 index 00000000..defed026 --- /dev/null +++ b/index.html @@ -0,0 +1,16 @@ + + + + Hello React + + + + + + + + +
+ + + diff --git a/package.json b/package.json new file mode 100644 index 00000000..8ed1b242 --- /dev/null +++ b/package.json @@ -0,0 +1,30 @@ +{ + "name": "react-tutorial", + "version": "0.0.0", + "description": "Code from the React tutorial.", + "main": "server.js", + "dependencies": { + "express": "3.12.1" + }, + "devDependencies": {}, + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1", + "start": "node server.js" + }, + "repository": { + "type": "git", + "url": "https://github.com/petehunt/react-tutorial.git" + }, + "keywords": [ + "react", + "tutorial", + "comment", + "example" + ], + "author": "petehunt", + "license": "MIT", + "bugs": { + "url": "https://github.com/petehunt/react-tutorial/issues" + }, + "homepage": "https://github.com/petehunt/react-tutorial" +} diff --git a/scripts/example.js b/scripts/example.js new file mode 100755 index 00000000..8fa001ed --- /dev/null +++ b/scripts/example.js @@ -0,0 +1,114 @@ +/** @jsx React.DOM */ + +var converter = new Showdown.converter(); + +var Comment = React.createClass({ + render: function() { + var rawMarkup = converter.makeHtml(this.props.children.toString()); + return ( +
+

+ {this.props.author} +

+ +
+ ); + } +}); + +var CommentBox = React.createClass({ + loadCommentsFromServer: function() { + $.ajax({ + url: this.props.url, + dataType: 'json', + 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) { + var comments = this.state.data; + comments.push(comment); + this.setState({data: comments}, function() { + // `setState` accepts a callback. To avoid (improbable) race condition, + // `we'll send the ajax request right after we optimistically set the new + // `state. + $.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: []}; + }, + componentWillMount: function() { + this.loadCommentsFromServer(); + setInterval(this.loadCommentsFromServer, this.props.pollInterval); + }, + render: function() { + return ( +
+

Comments

+ + +
+ ); + } +}); + +var CommentList = React.createClass({ + render: function() { + var commentNodes = this.props.data.map(function(comment, index) { + return ( + // `key` is a React-specific concept and is not mandatory for the + // purpose of this tutorial. if you're curious, see more here: + // http://facebook.github.io/react/docs/multiple-components.html#dynamic-children + + {comment.text} + + ); + }); + return ( +
+ {commentNodes} +
+ ); + } +}); + +var CommentForm = React.createClass({ + handleSubmit: function() { + var author = this.refs.author.getDOMNode().value.trim(); + var text = this.refs.text.getDOMNode().value.trim(); + this.props.onCommentSubmit({author: author, text: text}); + this.refs.author.getDOMNode().value = ''; + this.refs.text.getDOMNode().value = ''; + return false; + }, + render: function() { + return ( +
+ + + +
+ ); + } +}); + +React.renderComponent( + , + document.getElementById('content') +); diff --git a/server.js b/server.js new file mode 100644 index 00000000..4213ab59 --- /dev/null +++ b/server.js @@ -0,0 +1,20 @@ +var express = require('express'); +var app = express(); + +var comments = [{author: 'Pete Hunt', text: 'Hey there!'}]; + +app.use('/', express.static(__dirname)); +app.use(express.bodyParser()); + +app.get('/comments.json', function(req, res) { + res.setHeader('Content-Type', 'application/json'); + res.send(JSON.stringify(comments)); +}); + +app.post('/comments.json', function(req, res) { + comments.push(req.body); + res.setHeader('Content-Type', 'application/json'); + res.send(JSON.stringify(comments)); +}); + +app.listen(3000);