状態(state)とは
- コンポーネント内で管理する変数。
- local state 呼ばれる。
- propsとして子コンポーネントに渡せる。
何故stateを使うのか
- renderメソッドの中では値を変更してはいけない。 (無限ループになる可能性があるから)
- setState() セッターで値を変更する。
- stateの変更 = 再レンダーのきっかけ => ページリロードせずに表示を切り替えられる。
レンダリング/レンダー(render)とは : webブラウザのウィンドウ内にページ内容の描画を行うことを言う。とらゼミ01でも解説済み。
stateの設定方法
- functional componentはstateを持つことができないので、class componentが前提となる。
- constructor内で宣言する。
- オブジェクト型で記述。
例)
class Blog extends React.Component {
// コンストラクタ
constructor(props){
super(props)
this.state = {
isPublished : false
}
}
}
export default Blog;
stateの取得
- 同一コンポーネント内で取得するなら this.state.isPublished (コンポーネント内の変数内なのでthisをつけた後、stateのオブジェクトのキーであるisPublishedをつける)。
- 子コンポーネントで参照したい場合はpropsとして渡す。
子コンポーネントに渡す例)
class Blog extends React.Component {
// コンストラクタ
constructor(props){
super(props)
this.state = {
isPublished : false //stateの値。
}
}
// renderメソッド
render(){
return(
<>
<Article
title="React"
order={100}
isPublished={this.state.isPublished} //stateを渡す。
/>
</>
)
}
}
export default Blog;
子コンポーネント側の受け取る例)
import React from 'react'
const Article = (props) => {
return (
<div>
<h2>{props.title} + {props.order}</h2>
<label htmlFor='check'>公開状態</label> //ラベル設定は htmlForで行う。
<input type='checkbox' checked={props.isPublished} id='check'/>
</div>
)
}
export default Article;
これだとcheckboxに対するcheckedのstateがfalseのままなので永遠にクリックできない、なのでstateの値を変更する必要がある。
stateの変更方法。
- setState()を使う。
- 関数にラップするのが一般的。
- setState内に記述されたstateのみを変更。
例) render関数と同じファイルに記述。
togglePublished = () => {
this.setState({
isPublished : !this.state.isPublished
})
}
これを子コンポーネントで使うためには関数毎渡してやる必要がある。
アロー関数の形で渡す必要がある。
例)
render(){
return(
<>
<Article
title="React"
order={100}
isPublished={this.state.isPublished}
toggle={() => this.togglePublished()} // アロー関数。
/>
</>
)
}
何故関数は関数の形で渡してあげなければならないか?
render(){
return(
<>
<Article
toggle={this.togglePublished()} // ここ
/>
</>
)
}
この形で渡してしまうと、この時点で関数が実行されてしまい、その時点でstateが変更され無限レンダーに入ってしまうので、toggleを実行すると関数が実行されると言う形で渡す。
stateを子コンポーネントで受け取る。
const Article = (props) => {
return (
<div>
<h2>{props.title} + {props.order}</h2>
<label htmlFor='check'>公開状態</label>
// onClickの関数として受け取る。
<input type='checkbox' checked={props.isPublished} onClick={() => props.toggle} id='check'/>
</div>
)
}
再び無限レンダーを避けるため、onClickを発動した時関数が実行されるようにする。
onClick実行 -> toggle関数実行 -> togglePublished関数実行 -> setState()実行 -> state変更。