React入門その③ stateとprops
前回から新たに学んだことの自分用メモです。
前回とほぼ同じ機能の簡単なアプリケーションです。前回のものに比べて、「 この選択肢は既に存在します。 」というメッセージが出る機能を追加したくらいです。
新たに学んだ事
- Reactコンポーネント
- React.Component から派生したコンポーネントを作る
- コンポーネントは入れ子にできる。
- React props(プロパティ)
- 子となるコンポーネントに値や関数を渡す(読み取り専用)
- 関数が実行できるよう親コンポーネントの contructor で bind が必要
- この書き方は見苦しくて苦痛。回避策あり。
- state
- Stateless functional component(関数コンポーネント)
- コンポーネントが状態を持たない場合(例:決まったヘッダーを表示するだけのコンポーネント)は、 React.Componen から派生したクラスのコンポーネントを使わず、const Example =(props) => { return (…); } という形式を用いることができる。
- defaultProps
- props(プロパティ)の初期値を設定する。
- state の初期値として props を指定し、その初期値を defaultProps で指定する方法がある。
コード
class IndecisionApp extends React.Component { constructor(props) { super(props); this.handleDeleteOptions = this.handleDeleteOptions.bind(this); this.handlePick = this.handlePick.bind(this); this.handleAddOption = this.handleAddOption.bind(this); this.state = { options: props.options }; } handleDeleteOptions() ({ this.setState(() => { options: [] })); } handlePick() { const randomNum = Math.floor(Math.random() * this.state.options.length); const option = this.state.options[randomNum]; alert(option); } handleAddOption(option) { if (!option) { return "適切な値を入力してください"; } else if (this.state.options.indexOf(option) > -1) { return "この選択肢は既に存在します。"; } this.setState(prevState => ({ options: prevState.options.concat(option) })); } render() { const subtitle = "あなたの人生をコンピュータに委ねる。"; return ( <div> <Header subtitle={subtitle} /> <Action hasOptions={this.state.options.length > 0} handlePick={this.handlePick} /> <Options options={this.state.options} handleDeleteOptions={this.handleDeleteOptions} /> <AddOption handleAddOption={this.handleAddOption} /> </div> ); } } IndecisionApp.defaultProps = { options: [] }; const Header = (props) => { return ( <div> <h1>{props.title}</h1> {props.subtitle && <h2>{props.subtitle}</h2>} </div> ); } Header.defaultProps = { title: "優柔不断" }; const Action = (props) => { return ( <div> <button onClick={props.handlePick} disabled={!props.hasOptions} > 私はどうすればいい? </button> </div> ); } const Options = (props) => { return ( <div> <button onClick={props.handleDeleteOptions}>すべて削除</button> <ol> {props.options.map(option => ( <Option key={option} optionText={option} /> ))} </ol> </div> ); } const Option = (props) => { return ( <div> <li>{props.optionText}</li> </div> ); } class AddOption extends React.Component { constructor(props) { super(props); this.handleAddOption = this.handleAddOption.bind(this); this.state = { error: undefined }; } handleAddOption(e) { e.preventDefault(); const option = e.target.elements.option.value.trim(); const error = this.props.handleAddOption(option); this.setState(() => ({ error })); } render() { return ( <div> {this.state.error && <p>{this.state.error}</p>} <form onSubmit={this.handleAddOption}> <input type="text" name="option" /> <button>選択肢の追加</button> </form> </div> ); } } ReactDOM.render(<IndecisionApp />, document.getElementById("app"));
ディスカッション
コメント一覧
まだ、コメントがありません