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

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

水色

わたしについて

この記事は2016年に投稿した記事で、今では古い書き方になっているかもしれませんが、考え方は一緒です。(2020/4/30)

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

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

propsとstateの簡単な説明

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

<ParentComponent />

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

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

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

この親が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>

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

<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 && <GroundChildComponent />;
 return (
  <div>{DOM}</div>
  )
}

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

ふう。

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

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

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

今回のコード全部


「武骨日記の」プライバシーポリシーに関して
プライバシーポリシー
個人情報取り扱いに関して

サイトTOP
私は何者か
29歳よしもと芸人がWebデザイナー未経験で学校に通い5年後フリーランスのフロントエンドエンジニアになるためにやった9つのこと
フロント記事
フロントエンドエンジニア
フロントエンド記事(タグ)
TypeScript
TypeScript練習問題集
【TypeScript】TypeSript中級者になる為に知っておくと良い108個のこと
JavaScript練習問題
styled-componentsの使い方
SCSS問題集
GraphQL「Apollo x Relay-Style-Cursor-Pagination(リレースタイルカーソルページネーション)」
recomposeと仲良くなりたい
機動戦士FlowType
初めてReactNativeWebを触ってみて
Ramda.jsシグネチャの読み方
環境変数の話
いちごタルトの作り方
フロントエンドエンジニア豚汁の作り方


「武骨日記の」プライバシーポリシーに関して
プライバシーポリシー

株式会社TerraceTechについて
最近起業しました。
株式会社TerraceTech

SNS
しずかなインターネット kenjimorita
インド旅 instagram
適当な日常写真 instagram
シュールさーん instagram
シュールさーん LINEスタンプ
もりたけんじTwitter
ネタ帳Twitter
note

FaceBook -kennji.morita-

わたしが結成しているWebチームではWeb未経験者、フリーランスの方へのお仕事を紹介しています。
また個人レッスンしてほしい生徒も募集中です。
もしご興味ある方はチャットからご連絡ください。

※業務連絡やお久しぶり連絡もチャットからお願いします。