公式の私的まとめ
この記事でのコードは公式を参考にしている。
イベント処理
Reactのイベント処理はブラウザのDOMと似ている
違いは以下
- Reactのイベントは小文字ではなくcamelCase
- JSXではイベントハンドラとして文字列じゃなくて関数を渡す
<button onclick="activateLasers()">
Activate Lasers
</button>
<button onClick={activateLasers}>
Activate Lasers
</button>
このようにReactでは属性名がcamelCaseで、イベントが関数で渡されている
またReactではfalseを返してもデフォルト動作を抑制できない
<a href="#" onclick="console.log('The link was clicked.'); return false">
Click me
</a>
React では、以下のようになる
function ActionLink() {
function handleClick(e) {
e.preventDefault();
console.log('The link was clicked.');
}
return (
<a href="#" onClick={handleClick}>
Click me
</a>
);
}
e.preventDefault();として抑制している。
eはブラウザと五感を持っている
ReactはDOM生成後にaddEventListenerでイベントを追加する必要はない
代わりに最初にレンダーされるときにリスナを指定する。
JSXのコールバックのthis
javascriptではクラスにメソッドはデフォルトでバインドされない
this.handleClickへのバインドを忘れるとonClickで実際に関数が呼ばれたときに、thisはundefindとなる。
Reactに限らずjavascriptはそういうもの
onClick={this.handleClick}のように()をつけないでメソッドを参照するときそのメソッドはバインドしておく必要がある
とりあえずイベントを使うときはバインドしておけばいいと思う
イベントハンドラに引数を渡す
idという行のIDがあるとき、以下はちゃんと動作する
//bind
<button onClick={this.deleteRow.bind(this, id)}>Delete Row</button>
ReactイベントeはIDの2番めの引数として渡される。
id以降の追加の引数は自動的に転送される。
意味ワカンネ
条件付きレンダー
以下は公式のログイン状況でどちらかを表示するコンポーネント
function UserGreeting(props) {
return <h1>Welcome back!</h1>;
}
function GuestGreeting(props) {
return <h1>Please sign up.</h1>;
}
function Greeting(props) {
const isLoggedIn = props.isLoggedIn;
if (isLoggedIn) {
return <UserGreeting />;
}
return <GuestGreeting />;
}
function LoginButton(props) {
return (
<button onClick={props.onClick}>
Login
</button>
);
}
function LogoutButton(props) {
return (
<button onClick={props.onClick}>
Logout
</button>
);
}
class LoginControl extends React.Component {
constructor(props) {
super(props);
this.handleLoginClick = this.handleLoginClick.bind(this);
this.handleLogoutClick = this.handleLogoutClick.bind(this);
this.state = {isLoggedIn: false};
}
handleLoginClick() {
this.setState({isLoggedIn: true});
}
handleLogoutClick() {
this.setState({isLoggedIn: false});
}
render() {
const isLoggedIn = this.state.isLoggedIn;
let button;
if (isLoggedIn) {
button = <LogoutButton onClick={this.handleLogoutClick} />;
} else {
button = <LoginButton onClick={this.handleLoginClick} />;
}
return (
<div>
<Greeting isLoggedIn={isLoggedIn} />
{button}
</div>
);
}
}
ReactDOM.render(
<LoginControl />,
document.getElementById('root')
);
以下の手順で切り替えをしている。
- Reactがを実行してLoginControlクラスのコンストラクタを実行する。そこでは2つログイン状況を変更するsetStateを実行する関数がバインドされている。更にstateの初期値を設定する。
- Reactはその後render()を実行。ログイン状況を判定してボタン要素を再描画するかを決めている。
- render()内でそこでGreetingクラスが呼ばれる。その際に、isLoggedInプロパティ(今のログイン状況の値が入っている)をpropsとして渡している。そこでも判定して表示するReactエレメントを返してボタン要素も描画する。 ##論理 && 演算子による 他の方法で条件付きのレンダーができるが、今は混乱するからif文の方法だけにしておく。
リストとkey
以下はjavascriptでリストを変換する方法
const numbers = [1, 2, 3, 4, 5];
const doubled = numbers.map((number) => number * 2);
console.log(doubled);
上記は値を2倍にした配列を生成している。
Reactも同様にリスト変換できる
複数のコンポーネントをレンダリング
const numbers = [1, 2, 3, 4, 5];
const listItems = numbers.map((number) =>
<li>{number}</li>
);
エレメントを配列に格納している
function NumberList(props) {
const numbers = props.numbers;
const listItems = numbers.map((number) =>
<li key={number.toString()}>
{number}
</li>
);
return (
<ul>{listItems}</ul>
);
}
const numbers = [1, 2, 3, 4, 5];
ReactDOM.render(
<NumberList numbers={numbers} />,
document.getElementById('root')
);
上記は先のコードを同じ出力
<li key={number.toString()}>
を書かないと
Warning: Each child in a list should have a unique "key" prop.
という警告を受ける
これはkeyを与えとという意味
key
これはReactがどの要素が変更されたかをReactが認識するために使っている
フォーム
通常のフォームを使うとページ遷移が起こるが大半はそうなってほしくない
ここでは制御されたコンポーネントなるテクニックを学ぶらしい
制御されたコンポーネント
HTMLではフォーム要素は自身で状態を保持している
Reactは変更されうる状態はstateに保持される
Reactのstateを信頼できる雄一の情報とすることで、ユーザのフォーム入力で起こることも制御できる。
これを制御されたコンポーネントというらしいがイマイチピンとこない
以下はその例
class NameForm extends React.Component {
constructor(props) {
super(props);
this.state = {value: ''};
this.handleChange = this.handleChange.bind(this);
this.handleSubmit = this.handleSubmit.bind(this);
}
handleChange(event) {
this.setState({value: event.target.value});
}
handleSubmit(event) {
alert('A name was submitted: ' + this.state.value);
event.preventDefault();
}
render() {
return (
<form onSubmit={this.handleSubmit}>
<label>
Name:
<input type="text" value={this.state.value} onChange={this.handleChange} />
</label>
<input type="submit" value="Submit" />
</form>
);
}
}
ポイント
- inputのvalueをthis.state.valueとしている
- onChangeで入力するたびにstateが変わることでフォームを送信する頃には最終入力値が送信される
制御されたコンポーネントでユーザ入力がReactのstateで制御できる
textarea
<textarea value={this.state.value} onChange={this.handleChange} />
Reactではvalue属性を使う
file input
<input type="file" />
これは読み取り専用で制御はできない
複数入力の処理
それぞれのname属性を追加すればevent.target.nameで処理の選択ができる