Skip to content

Commit fc4b6c0

Browse files
authored
Merge pull request #27 from linuxonrails/port_04_callback_from_ts_to_js_#12
Port 04 Callback From TS to JS (ES6 >ES6) Issue #12
2 parents e0dfad8 + 546a0e5 commit fc4b6c0

File tree

9 files changed

+327
-0
lines changed

9 files changed

+327
-0
lines changed

04 Callback/package.json

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
{
2+
"name": "samplereact",
3+
"version": "1.0.0",
4+
"description": "In this sample we are going to setup the basic plumbing to \"build\" our project and launch it in a dev server.",
5+
"main": "index.js",
6+
"scripts": {
7+
"start": "webpack-dev-server --inline",
8+
"test": "echo \"Error: no test specified\" && exit 1"
9+
},
10+
"author": "",
11+
"license": "ISC",
12+
"devDependencies": {
13+
"babel-core": "^6.18.2",
14+
"babel-loader": "^6.2.7",
15+
"babel-plugin-transform-runtime": "^6.15.0",
16+
"babel-preset-es2015": "^6.18.0",
17+
"babel-preset-react": "^6.16.0",
18+
"css-loader": "^0.25.0",
19+
"file-loader": "^0.9.0",
20+
"html-webpack-plugin": "^2.24.1",
21+
"style-loader": "^0.13.1",
22+
"url-loader": "^0.5.7",
23+
"webpack": "^1.13.3",
24+
"webpack-devserver": "0.0.6"
25+
},
26+
"dependencies": {
27+
"bootstrap": "^3.3.7",
28+
"react": "^15.3.2",
29+
"react-dom": "^15.3.2"
30+
}
31+
}

04 Callback/readme.md

Lines changed: 121 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,121 @@
1+
# 04 Callback + State
2+
3+
In this sample we are going to refactor the previous sample **03 State**.
4+
5+
We'll update the name property only when the user clicks on
6+
a _change_ button, we will simplify the event itself as well.
7+
8+
Obviously, we will take the sample **03 State** as a starting point.
9+
10+
Summary steps:
11+
12+
- Add a button to the `EditName` component and a handler function for this.
13+
- Submit the name only when the user clicks on the button.
14+
- Update the `app` component to handle the new simplified event.
15+
16+
## Prerequisites
17+
18+
Install [Node.js and npm](https://nodejs.org/en/) (v6.6.0 or newer) if they are not already installed on your computer.
19+
20+
> Verify that you are running at least node v6.x.x and npm 3.x.x by running `node -v` and `npm -v` in a terminal/console window. Older versions may produce errors.
21+
22+
## Steps to build it
23+
24+
- Copy the content of the `03 State` folder to an empty folder for the sample
25+
and make this your current folder.
26+
27+
- Install the npm packages described in the `package.json` and verify that it works:
28+
29+
```bash
30+
npm install
31+
```
32+
33+
- Since we are going to use an internal handler, we'll transform the `NameEditComponent`
34+
from a stateless component into a class component, then we will add some refactor on the naming.
35+
36+
The `nameEdit.jsx` file should looks like this:
37+
38+
```jsx
39+
import * as React from 'react';
40+
41+
export class NameEditComponent extends React.Component {
42+
43+
constructor(props) {
44+
super(props);
45+
// Watch out what would happen if we get this user name via an AJAX callback
46+
// you will find a different implementatin on 05 sample
47+
this.state = {
48+
editingName: this.props.initialUserName,
49+
};
50+
51+
this.onChange = this.onChange.bind(this);
52+
this.onNameSubmit = this.onNameSubmit.bind(this);
53+
}
54+
55+
onChange(event) {
56+
this.setState({ editingName: event.target.value });
57+
}
58+
59+
onNameSubmit() {
60+
this.props.onNameUpdated(this.state.editingName);
61+
}
62+
63+
render() {
64+
return (
65+
<div>
66+
<label htmlFor="editingName">Update Name:</label>
67+
<input value={this.state.editingName} onChange={this.onChange} id="editingName" />
68+
<input type="submit" value="Change" className="btn btn-default" onClick={this.onNameSubmit} />
69+
</div>
70+
);
71+
}
72+
}
73+
74+
NameEditComponent.propTypes = {
75+
initialUserName: React.PropTypes.string.isRequired,
76+
onNameUpdated: React.PropTypes.func,
77+
};
78+
```
79+
80+
- Let's wire this up in the `app.jsx` file.
81+
82+
```jsx
83+
export class App extends React.Component {
84+
constructor(props) {
85+
super(props);
86+
this.state = { userName: 'defaultUserName' };
87+
this.setUsernameState = this.setUsernameState.bind(this);
88+
}
89+
90+
setUsernameState(newName) {
91+
this.setState({ userName: newName });
92+
}
93+
94+
render() {
95+
return (
96+
<div>
97+
<HelloComponent userName={this.state.userName} />
98+
<NameEditComponent
99+
initialUserName="Javier Cansado"
100+
onNameUpdated={this.setUsernameState}
101+
/>
102+
</div>
103+
);
104+
}
105+
}
106+
107+
```
108+
109+
Now we've got a clear event, strongly typed and simplified (straight forward).
110+
111+
- Let's give it a try:
112+
113+
```bash
114+
npm start
115+
```
116+
117+
- Then, load http://localhost:8080/ in a browser to see the output.
118+
119+
![Browser Output](../99_readme_resources/04 Callback/browser_output.png "Browser Output")
120+
121+
Now, the greeting only change when the user clicks on the change button.

04 Callback/src/app.jsx

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
import React from 'react';
2+
import { HelloComponent } from './hello';
3+
import { NameEditComponent } from './nameEdit';
4+
5+
export class App extends React.Component {
6+
constructor(props) {
7+
super(props);
8+
this.state = { userName: 'defaultUserName' };
9+
this.setUsernameState = this.setUsernameState.bind(this);
10+
}
11+
12+
setUsernameState(newName) {
13+
this.setState({ userName: newName });
14+
}
15+
16+
render() {
17+
return (
18+
<div>
19+
<HelloComponent userName={this.state.userName} />
20+
<NameEditComponent
21+
initialUserName="Javier Cansado"
22+
onNameUpdated={this.setUsernameState}
23+
/>
24+
</div>
25+
);
26+
}
27+
}

04 Callback/src/hello.jsx

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
import * as React from 'react';
2+
3+
export const HelloComponent = props => (
4+
<h2>Hello user: {props.userName}!</h2>
5+
);
6+
7+
HelloComponent.propTypes = {
8+
userName: React.PropTypes.string.isRequired,
9+
};

04 Callback/src/index.html

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
<!DOCTYPE html>
2+
<html>
3+
<head>
4+
<meta charset="utf-8">
5+
<title>Sample 03: State management</title>
6+
</head>
7+
<body>
8+
<h1>Sample app</h1>
9+
<div id="root"></div>
10+
</body>
11+
</html>

04 Callback/src/main.jsx

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
/* global document */
2+
3+
import React from 'react';
4+
import { render } from 'react-dom';
5+
import { App } from './app';
6+
7+
render(
8+
<App />
9+
, document.getElementById('root')
10+
);

04 Callback/src/nameEdit.jsx

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
import * as React from 'react';
2+
3+
export class NameEditComponent extends React.Component {
4+
5+
constructor(props) {
6+
super(props);
7+
// Watch out what would happen if we get this user name via an AJAX callback
8+
// you will find a different implementatin on 05 sample
9+
this.state = {
10+
editingName: this.props.initialUserName,
11+
};
12+
13+
this.onChange = this.onChange.bind(this);
14+
this.onNameSubmit = this.onNameSubmit.bind(this);
15+
}
16+
17+
onChange(event) {
18+
this.setState({ editingName: event.target.value });
19+
}
20+
21+
onNameSubmit() {
22+
this.props.onNameUpdated(this.state.editingName);
23+
}
24+
25+
render() {
26+
return (
27+
<div>
28+
<label htmlFor="editingName">Update Name:</label>
29+
<input value={this.state.editingName} onChange={this.onChange} id="editingName" />
30+
<input type="submit" value="Change" className="btn btn-default" onClick={this.onNameSubmit} />
31+
</div>
32+
);
33+
}
34+
}
35+
36+
NameEditComponent.propTypes = {
37+
initialUserName: React.PropTypes.string.isRequired,
38+
onNameUpdated: React.PropTypes.func,
39+
};

04 Callback/webpack.config.js

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
var path = require('path');
2+
var webpack = require('webpack');
3+
var HtmlWebpackPlugin = require('html-webpack-plugin');
4+
5+
var basePath = __dirname;
6+
7+
module.exports = {
8+
context: path.join(basePath, "src"),
9+
resolve: {
10+
extensions: ['', '.js', '.jsx']
11+
},
12+
entry: [
13+
'./main.jsx',
14+
'../node_modules/bootstrap/dist/css/bootstrap.css'
15+
],
16+
output: {
17+
path: path.join(basePath, 'dist'),
18+
filename: 'bundle.js'
19+
},
20+
devtool: 'source-map',
21+
devServer: {
22+
contentBase: './dist', //Content base
23+
inline: true, //Enable watch and live reload
24+
host: 'localhost',
25+
port: 8080,
26+
stats: 'errors-only'
27+
},
28+
module: {
29+
loaders: [
30+
{
31+
test: /\.jsx$/,
32+
loader: "babel-loader",
33+
exclude: /node_modules/,
34+
query: {
35+
plugins: ['transform-runtime'],
36+
presets : ['es2015', 'react']
37+
}
38+
},
39+
{
40+
test: /\.js$/,
41+
loader: 'babel-loader',
42+
exclude: /node_modules/,
43+
query: {
44+
presets: ['es2015']
45+
}
46+
},
47+
{
48+
test: /\.css$/,
49+
loader: 'style-loader!css-loader'
50+
},
51+
// Loading glyphicons => https://github.com/gowravshekar/bootstrap-webpack
52+
// Using here url-loader and file-loader
53+
{
54+
test: /\.(woff|woff2)(\?v=\d+\.\d+\.\d+)?$/,
55+
loader: 'url?limit=10000&mimetype=application/font-woff'
56+
},
57+
{
58+
test: /\.ttf(\?v=\d+\.\d+\.\d+)?$/,
59+
loader: 'url?limit=10000&mimetype=application/octet-stream'
60+
},
61+
{
62+
test: /\.eot(\?v=\d+\.\d+\.\d+)?$/,
63+
loader: 'file'
64+
},
65+
{
66+
test: /\.svg(\?v=\d+\.\d+\.\d+)?$/,
67+
loader: 'url?limit=10000&mimetype=image/svg+xml'
68+
}
69+
]
70+
},
71+
plugins: [
72+
// Generate index.html in /dist => https://github.com/ampedandwired/html-webpack-plugin
73+
new HtmlWebpackPlugin({
74+
filename: 'index.html', // Name of file in ./dist/
75+
template: 'index.html', // Name of template in ./src
76+
hash: true
77+
})
78+
]
79+
}
28.6 KB
Loading

0 commit comments

Comments
 (0)