フロントエンジニア芸人もりたけんじのreact

【Reactのstateとpropsの違いが知りたい!(変更・更新の仕方等デモあり)】過去のReact初心者の自分にpropsとstateの違いを説明する

【Reactのstateとpropsの違いが知りたい!(変更・更新の仕方等デモあり)】過去のReact初心者の自分にpropsとstateの違いを説明する

ややわかり始めたReact、1年前にこういう記事かいて、今結構検索でヒットするみたいなので
、過去の自分にちょっと説明したらこんな感じかなと思って書きます。

※ここの記事ではこのコードをできるだけ簡単に説明しています。説明と照らし合わせて確認していただけたら幸いです。(PCでご覧になると表示がわかりやすいです)

propsとstateの簡単な説明

下記コードをみてください。

<ParentComponent />

こういうコンポーネントがあって、
ParentComponentはこういうDOMを返すとします。

<div>
 <h1>親です</h1>
 <ChildComponent />
</div>

「返す」というのは、Reactではコンポーネント単位でrenderメソッドというものを必ず実装しなくてはならず、そのメソッドはDOMを返さなくてはなりません。
まだちょっとよく馴染みがない方は、
この<ParentComponent>という「コンポーネント」は「一つのまとまったコードを描画するようにコーディングする」と思っていただけたら理解早いかもしれません。
なので今回は上記のように返すとします。

この親がrenderメソッドで返すChildComponentコンポーネントは

<div>
 <h2>題名</h2>
 わたしの未来
</div>

というDOMを返すようにします。

なので最終的なの描画は

<!--ここからParentComponentが返すDOM -->
<div>
 <h1>親です</h1>
  <!--ここChildComponentが返すDOM -->
  <div>
  <h2>題名</h2>
  わたしの未来
  <!--ここまでChildComponentが返すDOM -->
  </div>
</div>
<!--ここまでParentComponentが返すDOM -->

こうなります(実際のというのはやや語弊がありますが、説明のため端的にいっています。)
この「わたし」のところを可変にしたいとします。(状態を管理するといいます)
その場合親のrenderメソッド内でpropsとして渡す(今回は親がstateとして管理する場合を説明)

<div>
 <h1>親です</h1>
  <ChildComponent name={this.state.name}/>
</div>

こう。(親から子供に値をわたすイメージです。)
で子供側では

<div>
  <h2>題名</h2>
  {this.props.name}の未来
</div>

このように参照する。(親から値を受け取るイメージです。)

これが何をしているのか最初のうちはわからなかった。
これは「name属性として子供のコンポーネントに親で管理しているthis.state.name値を渡しています。」
name属性というのは任意の名前でつけます。
なんでもいいです。
この
name={this.state.name}
のnameが属性
this.state.nameが状態です
name属性は子供から参照する際の
this.props.name

name部分にあたります。
例えばこれが
menber={this.state.name}
とされていたら
子供では
this.props.menberとしてthis.state.name値を受け取れるということです。

で、今回の場合
this.state.nameに初期値として「わたし」を設定します。(後述///code1をみてください。このようにします)

なぜ「親から値を渡して子供は受け取る」とかそんなことしているか??

親で値を管理すると
その値が変わると子供にその変更が伝わり、
その子供の子供に変更が伝わりと再レンダリングされます。
少し乱暴に言うと親のstate値が変わった子供のDOMしか再描画されないので、パフォーマンスよく描画できます。
またcomponentが状態を管理し、値は親から子供への一方通行で渡されるので分かりやすいんですね。

さらに可搬性が良くなります。部品部品で取り扱いやすくなります。

this.state.name。
これを「値を管理している」といいます。
可変にしたいプロパティを指定します

一方this.props.name。これは不変な値です。参照のみでここに値を直接変更してはいけません。
this.props.name = “morita”;
これは代入しちゃっています。
propsは親から値を受け取るか、初期値として設定するかですので、これをrenderメソッド内でしてはいけません。
propsはread only。読み取り専用です。こうしたい場合はstateに変更します。

ついでにいうと
this.state.name = “morita”;
これもアンチパターンです。
stateの更新はsetStateでします。
setState({name : name + “さん”});
こういうのはありです。
あとsetStateをrenderメソッド内で呼んではいけません

話を戻して、、

this.state.nameは状態が変わる値です。
例えば、下は子供Componentが

render(){
 return(
  <div>
   <h2>題名</h2>
   {this.props.name}の未来
  </div>
  )
}

renderメソッド内で親が渡している値this.props.[親の属性値](親でいうthis.state.name)の状態を参照しています

当然親のthis.state.name値が変わると参照している子供の値も変わるので状態が変わる度にレンダリングされます。
(ライフサイクルメソッド内のcomponentwillreceivepropsで描画をコントロールできますが。。それはまた)

これで親の状態が変わったらnameも変わる簡単なコンポーネントのできあがりですね。

親の方では

 

//code1
this.state = {
 name: 'わたし'
}

をdefaultとしたり
defaultはpropsとして自分自身の値を参照すればこのような書き方になりますよ

this.stata = {
 name : this.props.name
}
ChildComponent.defaultProps = {
 name : 'わたし'
}

babelをstage-0とすれば

static name = 'わたし'

こういう風にかけたり、

もしくは
親の

<ParentComponent name={"わたし"}>

とすれば初期設定できます

このようにして、UserActionがあったら
そのメソッド内で下の用に呼び出します。
例えばこうです

onClick = ()=>{
 const name = "あなた";
 this.setState({
  name: name
 });
}

このstateを管理している親のメンバメソッドでsetStateを呼び出すことでそれ以下のコンポーネントは再レンダリングされるので
このインスタンス

<ChildComponent name={this.state.name}/>

これが子供でよみこまれる時には
name={“あなた”}
が渡っています。

子供のrender時のここが変わる

<div>
 <h2>題名</h2>
 あなたの未来
</div>

こうなります。
これの何が嬉しいかは
これが下のようにリストとして表示したい場合、同じDOMを書くのはだるいので
コンポーネントを複数書く。
でもその中でレンダリングするDOMは固有のものにしたい。なんて時は

//ParentComponent内のrenderメソッド内で
<div>
 <h1>親です</h1>
 <ChildComponent num={1} name={this.state.name} />
</div>
<div>
 <h1>親です</h1>
 <ChildComponent num={2} name={this.state.name} />
</div>

子供にpropsとしてnumを渡すことでChildComponent内のrenderメソッド内でprops.this.numが1の時で挙動を変えれたりするんですね。

例 親から渡ってきたnumが1だったらclassNameを変えたりする

//ChildComponent内で
render(){
  const color = this.props.num === 1 ? 'red' : 'blue';
  return (
   <div className={color}>
    子供のDOM
   </div>
  )
}

//例 親から渡ってきたnumが1だったらさらにComponentを返す

//ChildComponent内で
render(){
 const DOM = this.props.num === 1 &amp;&amp; <GroundChildComponent />;
 return (
  <div>{DOM}</div>
  )
}

とか
子供の中で返すDOMやスタイルを変更したりする

ふう。

どうでしたでしょうか。。
Reactのpropsとstateがいまいち腑に落ちない方へ助けになれたら幸いです。

こちらに今回のdemoをはっ付けておきます(PCから見るとちゃんと描画されるみたい。。)

playground
https://github.com/kenmori/React-ES6-Flux-Playground/tree/master/playground

今回のコード全部

【 併せて読みたい 】

【REACT】REACTの動きを理解したい人の為の最小サンプル

【REACT × ES6 × FLUX】を手っ取り早く学びたい人の為にサンプル作ったよ【3の倍数と3が付くときだけ猫になるCOUNTER】

REACT × FLUX × ES6 [WIP]LINE風チャット

フロントエンド記事

よしもとクリエイティブエージェンシーOmOプロジェクト Youtube【凝視おじさん】 【チャンネル登録】→http://www.youtube.com/channel/UCbPCoIwpQ5_FyNEyYvYpNBA?sub_confirmation=1【instagram】→instagram 【twitter】→https://twitter.com/gyoushiojisan

(Visited 64 times, 1 visits today)