概要
React + ES6 + Webpackでチュートリアルを行ったのでES6バージョンのソースをメモ。
【本家】 https://facebook.github.io/react/docs/tutorial.html
ES6変換ソース一覧
webpack.config.js
/webpack.config.js
let path = require('path');
let webpack = require('webpack');
const PATHS = {
src: path.join(__dirname, 'src'),
www: path.join(__dirname, 'www')
};
module.exports = {
entry: [
`${PATHS.src}/App.jsx`
],
output: {
path: PATHS.www,
filename: 'bundle.js'
},
resolve: {
extensions: [
'',
'.js',
'.jsx'
]
},
plugins: [
new webpack.ProvidePlugin({
jQuery: 'jquery',
$: 'jqeury'
})
],
devtool: 'inline-source-map',
devServer: {
contentBase: './www',
port: 3000,
hot: false,
inline: true,
colors: true
},
module: {
loaders: [
// Babel
{
test: [
/\.jsx$/,
/\.js$/
],
loaders: [
'babel'
],
exclude: /node_modules/
},
// Sass
{
test: [
/\.scss$/
],
loaders: [
'style',
'css',
'sass'
]
},
// CSS & Bootstrap
{ test: /\.css$/, loader: 'style-loader!css-loader' },
{ test: /\.svg$/, loader: 'url-loader?mimetype=image/svg+xml' },
{ test: /\.woff$/, loader: 'url-loader?mimetype=application/font-woff' },
{ test: /\.woff2$/, loader: 'url-loader?mimetype=application/font-woff' },
{ test: /\.eot$/, loader: 'url-loader?mimetype=application/font-woff' },
{ test: /\.ttf$/, loader: 'url-loader?mimetype=application/font-woff' }
]
}
};
.babelrc
/.babelrc
{
"presets": [
"react",
"es2015"
]
}
App.jsx
/src/App.jsx
/*::::::::::::::::::::::::::::::::::
JS
:::::::::::::::::::::::::::::::::::*/
import React from 'react';
import ReactDOM from 'react-dom';
/*::::::::::::::::::::::::::::::::::
Components
:::::::::::::::::::::::::::::::::::*/
import CommentApp from './components/Comment/CommentApp';
/*::::::::::::::::::::::::::::::::::
InitialDOM
:::::::::::::::::::::::::::::::::::*/
let mountNode = document.getElementById('mountNode');
/*::::::::::::::::::::::::::::::::::
AppComponent Defined
:::::::::::::::::::::::::::::::::::*/
export default class App extends React.Component {
render() {
return (
<div className="container-fluid">
<CommentApp url="http://XXXXXXXXXX/dummy/comments.json" pollInterval={2000} />
</div>
);
}
}
/*::::::::::::::::::::::::::::::::::
ToDOMRendering
:::::::::::::::::::::::::::::::::::*/
ReactDOM.render(<App />, mountNode);
CommentApp.jsx
チュートリアルではCommentBox.jsxだったがAppで統一したかった為、名称変更。
/src/components/Comment/CommentApp.jsx
import React from 'react';
import CommentList from './CommentList';
import CommentForm from './CommentForm';
import $ from 'jquery';
export default class CommentApp extends React.Component {
constructor(props) {
super(props);
this.state = {
data: [
{
author: 'Jack',
text: 'just setting up my twttr'
},
{
author: 'Evu',
text: 'this tweet is nice'
}
]
};
this.loadCommentsFromServer = this.loadCommentsFromServer.bind(this);
this.handleCommentSubmit = this.handleCommentSubmit.bind(this);
}
componentDidMount() {
this.loadCommentsFromServer();
setInterval(this.loadCommentsFromServer, this.props.pollInterval);
}
loadCommentsFromServer() {
// Ajaxは一旦コメントアウトでstateベースで実装
// $.ajax({
// url: this.props.url,
// dataType: 'json',
// cache: false,
// success: (data) => { this.setState({ data }); },
// error: (xhr, status, err) => {
// console.log(this.props.url, status, err.toString());
// }
// });
this.setState({
data: this.state.data
});
}
handleCommentSubmit(comment) {
this.setState({
data: this.state.data.concat(comment)
});
}
render() {
return (
<div className="commentApp">
<h1>CommentApp</h1>
<CommentList data={this.state.data} />
<CommentForm onCommentSubmit={this.handleCommentSubmit} />
</div>
);
}
}
CommentApp.propTypes = {
data: React.PropTypes.array,
url: React.PropTypes.string,
pollInterval: React.PropTypes.number
};
CommentList.jsx
/src/components/Comment/CommentList.jsx
import React from 'react';
import Comment from './Comment';
export default class CommentList extends React.Component {
render() {
let commentNodes = this.props.data.map((comment, i) => {
return (
<Comment key={i} author={comment.author}>{comment.text}</Comment>
);
});
return (
<div className="commentList">
{commentNodes}
</div>
);
}
}
CommentList.propTypes = {
data: React.PropTypes.array
};
CommentForm.jsx
/src/components/Comment/CommentForm.jsx
import React from 'react';
export default class CommentForm extends React.Component {
constructor(props) {
super(props);
this.handleSubmit = this.handleSubmit.bind(this);
}
handleSubmit(e) {
// ブラウザ挙動停止
e.preventDefault();
// refの値を取得
let author = this.refs.author.value;
let text = this.refs.text.value;
if (!text || !author) return;
// サーバにデータを送信
this.props.onCommentSubmit({
author,
text
});
// 値を空にする
this.refs.author.value = '';
this.refs.text.value = '';
}
render() {
return (
<form
className="commentForm"
onSubmit={this.handleSubmit}
>
<input
type="text"
placeholder="YourName"
className="textArea"
ref="author"
/>
<input
type="text"
placeholder="Say Something..."
ref="text"
className="textArea"
/>
<input
type="submit"
value="Tweet"
/>
</form>
);
}
}
CommentForm.propTypes = {
onCommentSubmit: React.PropTypes.func
};
Comment.jsx
/src/components/Comment/Comment.jsx
import marked from 'marked';
import React from 'react';
export default class Comment extends React.Component {
render() {
let rawMarkup = marked(this.props.children.toString(), { sanitize: true });
return (
<div className="comment">
<h3 className="commentAuthor">
{this.props.author}
</h3>
<span dangerouslySetInnerHTML={{ __html: rawMarkup }} />
</div>
);
}
}
Comment.propTypes = {
author: React.PropTypes.string,
children: React.PropTypes.string
};
まとめ
やっぱりES6で書くと気持ちいい。
React関連の勉強をもっと進めよう。
gulpからWebpackに乗り換えたけど、設定さえ覚えればWebpackの方が便利かも。