-
今からはじめるReact.js〜propsとstate、それからrefs〜
- 2015年11月12日
- React
※この記事は
http://qiita.com/kuniken/items/a22adda392ccc30011b1
で投稿した内容と同じものです。
前回→今からはじめるReact.js〜React ver0.14〜
になります。
propsとstateの特徴
なんらかの一覧表コンポーネントを作る場合、コンポーネントに表示させたいものを指定する必要があるわけですが、React.jsではデータを管理するための2つの変数が用意されています。- props
- state
値を指定するタイミング | 値の変更可否 | |
---|---|---|
props | コンポーネント作成時 | NO |
state | コンポーネント作成後 | YES |
値の指定方法
props
<Component propsKey1="value1" propsKey="value2">
のようにコンポーネント作成時に指定します。
state
var Component = React.createClass({
componentDidMount:function(){
this.setState({stateKey1: "value1",
stateKey2: "value2"});
},
のようにコンポーネント作成後、任意のタイミングで指定します。
(componentDidMountというファンクションはReact.jsが用意したファンクションで、コンポーネント作成後に実行されるようになっています)
stateに値を設定する場合は、setStateを使うようにします。
this.state.stateKey1 = "value1"
という書き方は認められていないようです。
値の取得
セットされた値を取得する場合は、単純です。render:function(){
return (
<div>
<span>title:{this.props.propsKey1}</span>
<img src={this.state.storeKey1}/>
</div>
);
}
this.props.~
this.state.~
と書くだけです。
初期値の指定
propsとstateで定義した変数には必ずしも値が指定されない場合もあるかもしれません。 値が指定されていなくてもサービスとしては問題なく後続処理ができるようにしなければなりません。 以下のようにします。props
var Component = React.createClass({
getDefaultProps: function() {
return {
propsKey1: 'default value'
};
},
state
var Component = React.createClass({
getInitialState: function() {
return {
stateKey1: 'initial value'
};
},
stateの場合はファンクション名の通り、初期値を設定するイメージですね。
propsの型・必須指定
propsはコンポーネント外部から指定されるため、おかしな値が渡されること、そもそも必須なのに値が渡されないかもしれないことを考慮したほうが良いかもしれません。 propTypesで定義することで型・必須指定を明確化できます。var Component = React.createClass({
propTypes:{
propsKey1: React.PropTypes.string.isRequired,//型:String、指定必須
propsKey2: React.PropTypes.number //型:number
},
詳細は、開発元サイトが詳しいです。
https://facebook.github.io/react/docs/reusable-components.html
不正な値を渡したり、指定必須なのに値を渡していなかったりすると、以下のように、デベロッパーツールのコンソールにエラーが表示されます。
フォームとリストを作成してみる
以上を踏まえて、ボディにフォームとリストを表示できるようにしてみます。 仕様としては、フォームで入力したデータを追加ボタンをクリックすることでリストに追記していく、というシンプルなものです。 body.jsxを書き換えていきます。//body.jsx
var React = require('react');
var ReactDOM = require('react-dom');
//ボディの定義
var Body = React.createClass({
render: function(){
return (
<UserBox/>
);
}
});
BodyではUserBoxコンポーネントを表示するようにしました。
UserBoxコンポーネントは入力フォームとリストをまとめたコンポーネントです。
データのやり取りは下図の通りです。
//body.jsx
//フォームとリストを一つにしたもの
var UserBox = React.createClass({
getInitialState:function(){
return {userData:[]};
},
handleAddUser:function(name, mail){
var data = this.state.userData;
data.push({name: name, mail: mail});
this.setState({userData: data});
},
render:function(){
return(
<div style={{width:"300px"}}>
<UserForm addUser={this.handleAddUser}/>
<hr/>
<UserList userData={this.state.userData}/>
</div>
);
}
});
UserBoxコンポーネントでは、ユーザーデータの一覧を持てるよう、stateにuserDataを保持するようにしました。
初期値として、getInitialStateで空の配列を代入しておきます。
次にフォームで追加ボタンをクリックしたら、stateのuserDataに値が追加されるようにするためのイベントを作成しました(handleAddUser)。
最後にrenderですが、
handleAddUserがフォームの追加ボタンをクリックした時に呼ばれるようにしたいため、UserFormのpropsであるaddUserにhandleAddUserを指定しています。
また、一覧で表示されるデータとして、UserListのpropsであるuserDataに、UserBoxのstateであるuserDataを指定しています。
//body.jsx
//リストそのものを表示するコンポーネントを定義
var UserList = React.createClass({
propTypes:{
userData:React.PropTypes.arrayOf(React.PropTypes.object).isRequired
},
render:function(){
var UserNodes = this.props.userData.map(function(user, index){
return (
<User name={user.name} mail={user.mail} key={index}/>
);
});
return (
<table>
<tbody>
<tr>
<th>名前</th>
<th>メールアドレス</th>
</tr>
{UserNodes}
</tbody>
</table>
);
}
});
リストを表示するコンポーネントでは、propsであるuserDataについて一行ずつUserコンポーネントとして作成し、積み上げたものをUserNodesという変数に代入するようにしています。
Userコンポーネントは以下の通りです。
//body.jsx
//リスト一行分を表示するコンポーネントを定義
var User = React.createClass({
propTypes:{
name: React.PropTypes.string.isRequired,
mail: React.PropTypes.string
},
render:function(){
return (
<tr>
<td>{this.props.name}</td>
<td>{this.props.mail}</td>
</tr>
);
}
});
propsとして定義された名前とメールアドレスを表示するようにしています。
最後に入力フォームは以下の通りです。
//body.jsx
//ユーザーの入力フォームを定義
var UserForm = React.createClass({
propTypes:{
addUser:React.PropTypes.func.isRequired
},
handleSubmit:function(){
var name = ReactDOM.findDOMNode(this.refs.name).value.trim();
var mail = ReactDOM.findDOMNode(this.refs.mail).value.trim();
if (!name){
return;
}
this.props.addUser(name, mail);
ReactDOM.findDOMNode(this.refs.name).value = "";
ReactDOM.findDOMNode(this.refs.mail).value = "";
},
render:function(){
return (
<div>
<table>
<tbody>
<tr>
<td>
<label>名前</label>
</td>
<td>
<input type="text" ref="name"/>
</td>
</tr>
<tr>
<td>
<label>メールアドレス</label>
</td>
<td>
<input type="text" ref="mail"/>
</td>
</tr>
</tbody>
</table>
<div style={{textAlign:"right"}}>
<button onClick={this.handleSubmit}>追加</button>
</div>
</div>
);
}
});
module.exports = Body;
追加ボタンをクリックした際のonClickイベントとしてhandleSubmitを定義しています。
handleSubmitではinputに入力された値を取得し、propsのaddUserイベントに値を渡しています。
ここでは、ReactDOM.findDOMNodeというのとrefsというのを使っています。
refs
コンポーネントにはそれぞれ、refというコンポーネントを識別するための属性を持つことができます。 同一コンポーネント内の全てのrefはrefsというものにまとめられます。 上記のUserFormコンポーネントを例にすると、<input type="text" ref="name"/>
<input type="text" ref="mail"/>
とrefが定義されていますが、UserFormコンポーネントでthis.refs.name
またはthis.refs.mail
と指定すると、それぞれのコンポーネントにアクセスすることができるようになります。
コンポーネントのDOM要素を取得する場合は、ReactDOM.findDOMNodeを使用します。
getDOMNodeというのもあったのですが、Ver0.14で非推奨となっています。
var name = ReactDOM.findDOMNode(this.refs.name).value.trim();
のように使用します。
サンプルソース
https://github.com/kunitak/react-tutorial/tree/day5 次回→今からはじめるReact.js〜サーバーサイド〜この記事を書いた人 : 國田健史
スタッフブログタグ:
AWS bluebird css CSV docker docker compose electron ES6 es2015 Git Heroku ITコンサルティング JavaScript justinmind less mongoDB Node.js php PostgreSQL Private Space Promise React react-router reactjs Salesforce scss Selenium Builder selenium IDE Selenium WebDriver stylus TypeScript VirtualBox VisualStudioCode vue vuejs webpack システム開発プロジェクト セキュリティ ワイヤーフレーム 上流工程 卒FIT 帳票 要件定義 設計 電力小売業界
一覧へ戻る
AWS bluebird css CSV docker docker compose electron ES6 es2015 Git Heroku ITコンサルティング JavaScript justinmind less mongoDB Node.js php PostgreSQL Private Space Promise React react-router reactjs Salesforce scss Selenium Builder selenium IDE Selenium WebDriver stylus TypeScript VirtualBox VisualStudioCode vue vuejs webpack システム開発プロジェクト セキュリティ ワイヤーフレーム 上流工程 卒FIT 帳票 要件定義 設計 電力小売業界