【React基礎 #3】 propsとstateについて
Reactコンポーネントはpropsとstateの2種類を使ってデータを管理します。
それらを組み合わせることで、表示を変更したりイベントを発生させたりします。
propsとは
propsとは親コンポーネントから子コンポーネントに渡すことができる属性値です。
親コンポーネント内で使われている子コンポーネントに属性を設定することによって、propsとして子コンポーネントに値を渡せます。
またpropsは変更不可(イミュータブル)な値でないといけません。
<コンポーネント名 属性名=属性値 属性名=属性値 ... />
渡すことができる値
文字列、数値などJavaScriptで使えるデータ型であればなんでも渡すことができます。
属性値は{ }
内に記述しますが、文字列に関しては" "
で記述できます。
<User
name="Taro" // 文字列
age={15} // 数値
check={true} // 真偽
subject={['国語', '数学', '体育']} // 配列
body={{height: 164, weight: 58}} // オブジェクト
score={total(7, 4)} // 関数
/>
propsの渡し方
import React from 'react';
// 親コンポーネントApp
const App = () => {
return <Greeting name="Taro"/>
}
// 子コンポーネントGreeting
const Greeting = (props) => {
return <div>Hi!{props.name}</div>
}
export default App;
// Hi!Taro
親コンポーネント(App)内の<Greeting />
にname="Taro"
の属性を設定して、子コンポーネント(Greeting)に渡します。
propsは子コンポーネント(Greeting)の引数によって渡されるので、メソッドチェーンで必要な値を利用します。
stateとは
stateとはコンポーネントの内部で状態を管理する変数で、クラスコンポーネントでのみ利用可能になります。
またstateはpropsとは逆で変更可能(ミュータブル)な値になります。
stateの設定
stateはクラスコンポーネントのconstructor
メソッド内でthis.state
にオブジェクト型で記述します。
class Counter extends React.Component {
constructor() {
super();
this.state = { counter: 0 };
}
}
stateの取得
【同コンポーネント内の場合】
this.state.key名
で取得できます。
class App extends React.Component {
constructor(props) {
super(props);
this.state = { name: 'Taro' };
}
render () {
return <div>Hi!{this.state.name}</div>
}
}
export default App;
// Hi!Taro
【子コンポーネントの場合】
propsで値を渡します。
class App extends React.Component {
constructor(props) {
super(props);
this.state = { name: 'Taro' };
}
render () {
return <Greeting name={this.state.name}/>
}
}
const Greeting = (props) => {
return <div>Hi!{props.name}</div>
}
export default App;
// Hi!Taro
<Greeting />
の属性値にthis.state.name
を設定して、子コンポーネントのpropsで取得します。
setStateについて
stateの値を変更する場合、直接変更するのではなく、setStateを使って変更します。
setStateが実行されると、コールバックでrenderが実行されて再レンダリングが行われます。
setStateを使うときは関数にラップするのが一般的です。
class Counter extends React.Component {
constructor(props) {
super(props);
this.state = { count: 0 };
}
handlePlusButton = () => {
this.setState({count: this.state.count + 1});
}
render() {
return (
<div>
<div>count: { this.state.count }</div>
<button onClick={this.handlePlusButton}>Click</button>
</div>
)
}
}
export default Counter;
-
Clickボタンを押すと
this.handlePlusButton
が実行されます。 -
this.setState
でstateのcountを現在のカウント「0」に「+1」します。 -
stateの値が「1」に変更され、
render
が実行されて再レンダリングします。
子コンポーネントに関数を渡す
親コンポーネントで宣言した関数を子コンポーネントで実行したい場合は、propsの属性値に関数型で渡す必要があります。
関数型ではなく直接入れた場合、renderですぐ実行されてしまい、無限ループが起こってしまうので注意が必要です。
関数を実行ではなく登録するために関数型で記述しましょう。
// 親コンポーネント
parent = () => {
// 実行内容
}
<コンポーネント名 child={() => parent()} />
// 子コンポーネント
<button onClick={() => child()}>ボタン</button>
【無限ループ例】
// 親コンポーネント
parent = () => {
// 実行内容
}
<コンポーネント名 child={parent()} />
// 子コンポーネント
<button onClick={child()}>ボタン</button>
propsとstateを使ったカウントアプリ
最後のまとめとしてpropsとstateとsetStateを使って実装したアプリです。
コード
import React from 'react';
class Counter extends React.Component {
constructor(props) {
super(props);
this.state = { count: 0 };
}
handlePlusButton = () => {
console.log('click')
this.setState({count: this.state.count + 1});
}
render() {
return <CounterBox count={this.state.count} counterPlus={() => this.handlePlusButton()}/>
}
}
const CounterBox = (props) => {
return (
<div>
<div>counfsaast: { props.count }</div>
<button onClick={()=> props.counterPlus()}>Click</button>
</div>
)
}
export default Counter;
まとめ
- propsは親コンポーネントから子コンポーネントに渡せる属性値で、変更不可(イミュータブル)な値でないといけない。
- stateはコンポーネントの内部で状態を管理する変数で、変更可能(ミュータブル)な値になる。
- stateの値を変更するにはsetStateを使う。
- 子コンポーネントに関数を渡す場合は、関数型で記述する。
さいごに
以上、propsとstateについてでした。
最初の頃はpropsとstateがゴチャゴチャになってしまうので、propsは属性でstateは状態ということを意識しながら慣れるまで実践あるのみです。
propsとstateはデータ管理において必須項目なのでマスターしたいところです。