React.jsでHelloWorld〜フォームの送信まで
React.jsでHello Worldを表示させる
<!-- index.html -->
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>React.js 初めの1歩</title>
<!-- 下記のJSを使えばReact.jsの環境は作れるので入れる -->
<script src="https://npmcdn.com/react@15.3.0/dist/react.js"></script>
<script src="https://npmcdn.com/react-dom@15.3.0/dist/react-dom.js"></script>
<script src="https://npmcdn.com/babel-core@5.8.38/browser.min.js"></script>
<!-- 今回は使わない -->
<script src="https://npmcdn.com/jquery@3.1.0/dist/jquery.min.js"></script>
<script src="https://npmcdn.com/remarkable@1.6.2/dist/remarkable.min.js"></script>
</head>
<body>
//React.jsで生成するHTML要素を挿入する場所
<div id="content"></div>
//JSタグの中に書いていく.
<script type="text/babel">
// Reactにおけるコンポーネントの作成(オブジェクト)
var SampleBox = React.createClass({
render: function() {
return (
<div className="sampleBox">
<h1>初めてのReact.js</h1>
<div>Hello, World!</div>
</div>
);
}
});
//ReactDOM.render()
//第一引数..renderメソッドをもったコンポーネント(オブジェクト)を渡す
//第二引数..renderする位置を指定する
ReactDOM.render(
<SampleBox />,
document.getElementById('content')
);
</script>
</body>
</html>
*複数のComponentを渡すことができないため、最終的に1つにまとめる必要がある。
NG例
<body>
<div id="content"></div>
<script type="text/babel">
var SampleBox = React.createClass({
render: function() {
return (
//一番上の親要素が1つではないのでNG! :disappointed_relieved:
**<h1>初めてのReact.js</h1>**
**<div>Hello, World!</div>**
);
}
});
ReactDOM.render(
<SampleBox />,
document.getElementById('content')
);
</script>
</body>
動的に親要素内に子要素を追加する
<body>
<div id="content"></div>
<script type="text/babel">
var ParentBox = React.createClass({
render: function() {
return (
<div className="firstBox">
<h1>初めてのReact.js</h1>
<ChildBox /> //ChildBoxのRenderメソッドの中身を呼び出し
</div>
);
}
});
//子要素の作成
var ChildBox = React.createClass({
render: function() {
return (
<ul className="secondBox">
<li>初めてのReact.js</li>
<li>Hello, World!</li>
</ul>
);
}
});
ReactDOM.render(
<ParentBox />,
document.getElementById('content')
);
</script>
</body>
パラメーターのセットと表示(prop)
<body>
<div id="content"></div>
<script type="text/babel">
var ParentBox = React.createClass({
render: function() {
return (
<div className="firstBox">
<h1>初めてのReact.js</h1>
//パラメーターを用意
<ChildBox num="1" title="初めてのReact.js" word="Hello, World!"></ChildBox>
<ChildBox num="2" title="2回目のReact.js" word="Hello, World2!"></ChildBox>
</div>
);
}
});
var ChildBox = React.createClass({
render: function() {
return (
<div className="secondBox">
//取得したパラメーターを表示
<p>要素{this.props.num}</p>
<ul>
<li>{this.props.title}</li>
<li>{this.props.word}</li>
</ul>
</div>
);
}
});
ReactDOM.render(
<ParentBox />,
document.getElementById('content')
);
</script>
</body>
可変なパラメーターと不可変なパラメーターの扱い方(propとstate)
<body>
<div id="content"></div>
<script type="text/babel">
var ParentBox = React.createClass({
//stateの初期化
getInitialState() {
return {
articles: [
{"num": 1, "title": "初めてのReact.js", "word": "Hello, World!"},
{"num": 2, "title": "2回目のReact.js", "word": "Hello, World2!"}
]
}
},
render: function()
// articlesというstateの中身を受け取って、展開する
// DOMに反映する時にこの値が参照され、最小限の変更にするために行う
// ちなみにDev環境でkeyを指定しないとコンソールにエラーがでる
var articles = this.state.articles.map((article) => {
return <ChildBox num={article.num} key={article.num} title={article.title} word={article.word}/>
});
return (
<div className="firstBox">
<h1>初めてのReact.js</h1>
{articles}
</div>
);
}
});
var ChildBox = React.createClass({
render: function() {
return (
<div className="secondBox">
<p>要素{this.props.num}</p>
<ul>
<li>{this.props.title}</li>
<li>{this.props.word}</li>
</ul>
</div>
);
}
});
ReactDOM.render(
<ParentBox />,
document.getElementById('content')
);
</script>
</body>
jsonファイルからデータを取り出し表示する
<body>
<div id="content"></div>
<script type="text/babel">
var ParentBox = React.createClass({
// JsonファイルをAjaxでリクエストを送り、Jsonの中身をstateに入れる
// ReactDOM.renderで、リクエストの送り先をPROP
getJson: function() {
$.ajax({
url: this.props.url,
dataType: 'json',
cache: false,
success: function(articles) {
this.setState({articles: articles});
}.bind(this),
error: function(xhr, status, err) {
console.error(this.props.url, status, err.toString());
}.bind(this)
});
},
getInitialState() {
return {
articles: []
}
},
componentDidMount: function() {
//getJsonを呼び出す
this.getJson();
// 2秒ごとにgetJsonを動かす設定
setInterval(this.getJson, this.props.pollInterval);
},
render: function() {
var articles = this.state.articles.map((article) => {
return <ChildBox num={article.num} key={article.num} title={article.title} word={article.word}/>
});
return (
<div className="firstBox">
<h1>React.js 初めの1歩</h1>
{articles}
</div>
);
}
});
var ChildBox = React.createClass({
render: function() {
return (
<div className="secondBox">
<h2>{this.props.title}</h2>
<p>要素{this.props.num}</p>
<p>{this.props.word}</p>
</div>
);
}
});
//propにリクエストURLとIntervalの時間を設定
ReactDOM.render(
<ParentBox url="sample.json" pollInterval={2000} />,
document.getElementById('content')
);
</script>
</body>
フォームで投稿した値をstateに入れて保持する
<body>
<div id="content"></div>
<script type="text/babel">
var ParentBox = React.createClass({
//ParentBoxで生成したURLのpropにJson取得リクエストを送る
getJson: function() {
$.ajax({
url: this.props.url,
dataType: 'json',
cache: false,
success: function(articles) {
// 取得した内容をstateにぶちこむbutikomu
this.setState({articles: articles});
}.bind(this),
error: function(xhr, status, err) {
console.error(this.props.url, status, err.toString());
}.bind(this)
});
},
// フォームで送信された内容を state articles に追加し、state articles を再構築
handleArticleSubmit: function(article) {
//現在の state articlesを取得
var articles = this.state.articles;
// 適当にid と numを追加
article.id = Date.now();
article.num = Date.now();
// フォームで送信された値を 追加
var newArticles = articles.concat([article]);
// state に再追加
this.setState({articles: newArticles});
// TODO DBに入れる場合、ここにPOSTのリクエストを書く
},
getInitialState() {
return {
articles: []
}
},
componentDidMount: function() {
this.getJson();
// Jsonファイルを見に行き、フォームで送信した値が消えるためコメントアウト
//setInterval(this.getJson, this.props.pollInterval);
},
render: function() {
var articles = this.state.articles.map((article) => {
return <ChildBox num={article.num} key={article.num} title={article.title} word={article.word}/>
});
return (
<div className="firstBox">
<h1>React.js 初めの1歩</h1>
{articles}
<ArticleForm onArticleSubmit={this.handleArticleSubmit}/>
</div>
);
}
});
var ChildBox = React.createClass({
render: function() {
return (
<div className="secondBox">
<h2>{this.props.title}</h2>
<p>要素{this.props.num}</p>
<p>{this.props.word}</p>
</div>
);
}
});
var ArticleForm = React.createClass({
getInitialState: function() {
return {title: '', word: ''};
},
handleTitleChange: function(e) {
this.setState({title: e.target.value});
},
handleWordChange: function(e) {
this.setState({word: e.target.value});
},
handleSubmit: function(e) {
// 入れないとページのリロードが走る
e.preventDefault();
// 空白を消す
var title = this.state.title.trim();
var word = this.state.word.trim();
// バリデーションはここで行う
if (!word || !title) {
return;
}
this.props.onArticleSubmit({title: title, word: word});
// テキストフィールドに保持していた stateを消す
this.setState({title: '', word: ''});
},
render: function() {
return (
<form className="articleForm" onSubmit={this.handleSubmit}>
<input type="text" placeholder="タイトル" value={this.state.title} onChange={this.handleTitleChange}/>
<input type="text" placeholder="本文" value={this.state.word} onChange={this.handleWordChange}/>
<input type="submit" value="Post" />
</form>
);
}
});
ReactDOM.render(
<ParentBox url="sample.json" pollInterval={2000} />,
document.getElementById('content')
);
</script>
</body>
参考記事
React チュートリアル
https://facebook.github.io/react/docs/tutorial-ja-JP.html
React.jsのProp
http://qiita.com/koba04/items/bc13d1f42964278ae14e
React.js + CSS
http://qiita.com/koba04/items/0e81a04262e1158dbbe4
React.jsのComponent Lifecycle
http://qiita.com/koba04/items/66e9c5be8f2e31f28461