Reactの続きです。前回はReactプロジェクトでクラスコンポーネントを作成しました。今回はステートを事始ます。setState()
による値の変更と、setInterbal()
によるタイマー処理、onClick
属性のイベント処理をやってみます。それではいきましょう!
【目次】
- 前回のおさらい
- ステートで「状態管理」をする!
- App.js(変更前)
- コンストラクタにステートの初期値を設定
- setState()でステートを変更
- タイマー処理(setInterval())でステートを変更する
- クリックイベントでステートを変更
- 最後に
※参考:前回記事
【React】Reactプロジェクトでクラスコンポーネント作成、入れ子、ファイル分割まで - クモのようにコツコツと
※参考:Reactでやってみたことまとめ qiita.com
前回のおさらい
今回も掌田さんの「React.js & Next.js入門」を参考に進める。
- 作者:掌田津耶乃
- 発売日: 2019/08/30
- メディア: Kindle版
前回はコンポーネントの属性に値を入れて固有の内容にした。
Imgコンポーネントを
render() { return <img src={logo} className="App-logo" alt="logo" style={this.style} /> }
Reactコンポーネントに入れ子にして
<div className="App-images"> <Img align="left" /> <Img align="center" /> <Img align="rignt" /> </div>
aline
属性で値を設定
さらにReactコンポーネントのレンダリングで
ReactDOM.render( <React.StrictMode> <App title="クモのようにコツコツと" message="Reactコンポーネントもコツコツと!" /> </React.StrictMode>, document.getElementById('root') );
title
属性とmessage
属性に値を設定
※参考:【React】Reactプロジェクトでクラスコンポーネント作成、入れ子、ファイル分割まで - クモのようにコツコツと
ステートで「状態管理」をする!
こうした値は「Read only」で変更をすることができない。
それを変更するのが「ステート」による状態管理!
state と props の違いは何ですか?
どちらもレンダー結果に影響を及ぼす情報を持ってはいますが、ある重要な一点が異なっています。つまり、props は(関数引数のように)コンポーネントへ渡されるのに対し、state は(関数内で宣言された変数のように)コンポーネントの内部で制御されます。
props
と違い、値を更新することができるのがstate
。
「状態管理」についてはVue.jsのVuexをやるときに調べた。このときReactには「Redux」があることを知った。
※参考:【Vue.js】Vuexの「状態管理」はいったい何の状態を管理しているのか調べた - クモのようにコツコツと
今回の段階ではまだReduxは使わずにstate
を利用する。
App.js(変更前)
App.js(変更前)
import React from 'react'; import Img from './Img'; import './App.css'; class App extends React.Component { constructor(props) { super(); this.title = props.title; this.message = props.message; } render() { return <div className="App"> <header className="App-header"> <div className="App-images"> <Img align="left" /> <Img align="center" /> <Img align="rignt" /> </div> <h1>{this.title}</h1> <p>{this.message}</p> </header> </div> } } export default App;
ここでApp
コンポーネントを設定している。
コンストラクタにステートの初期値を設定
ステートの初期値設定
ステートの初期値はこのような書き方をする。
this.state = {キー: 値}
this.state
の中はオブジェクト(連想配列)
コンストラクタを修正
コンストラクタにステートの初期値を設定する
constructor(props) { super(); this.state = { message: 'Reactステートもコツコツと!' } }
JSXにはstate
とprops
を設定して見る。
<h1>初めてのステート</h1> <p>{this.state.message}</p> <p>{this.props.message}</p>
なお、index.jsx上のAppコンポーネントには前回設定したmessage
属性がある。
ReactDOM.render( <React.StrictMode> <App message="Reactコンポーネントもコツコツと!" /> </React.StrictMode>, document.getElementById('root') );
ブラウザ挙動
ターミナルでReact起動!
npm start
おお、表示された!
上の行はstate
、下の行はprops
が読み込まれている。props
の値はAppコンポーネントのmessage
属性の値。state
ではこれは無視される。
App.js全体
import React from 'react'; import Img from './Img'; import './App.css'; class App extends React.Component { constructor(props) { super(); this.state = { message: 'Reactステートもコツコツと!' } } render() { return <div className="App"> <header className="App-header"> <div className="App-images"> <Img align="left" /> <Img align="center" /> <Img align="rignt" /> </div> <h1>初めてのステート</h1> <p>{this.state.message}</p> <p>{this.props.message}</p> </header> </div> } } export default App;
setState()でステートを変更
setState()
を使うと値を変更できる。下記の2つの方法がある。
// オブジェクトを渡す this.setState({ キー: 値 }); // 関数渡す this.setState((state) => ({ キー: 値 }));
オブジェクト(連想配列)の方が見た目はシンプルだが、ステートを意図通りに変更されない可能性があるため、関数を渡す方がいい。
setState() は、引数に オブジェクトが渡された場合 に、 state を即時にアップデートすることを 保証しません。 Reactは、パフォーマンスを高めるため、複数の setState() を単一の更新にバッチするためです。 そのため、1つの関数内で state の更新を連続的に行うときは、引数に関数を渡しましょう。
※参考:React の setState() の引数が関数の場合とオブジェクトの場合の違いについて整理する - Qiita
タイマー処理(setInterval())でステートを変更する
タイマー処理
タイマー処理setInterval()
を使って時間毎に変化させる。
setInterval(() => { 処理 }, 時間);
下記はJSXの時に使ったsetInterval()
※参考:【React】JSXレンダリングとタイマー処理(setInterval())の関係を理解する - クモのようにコツコツと
App.js修正
App.jsのコンストラクタを修正
constructor(props) { super(props); this.state = { msg1: "羊が", num: 1, msg2: "匹" }; let count = setInterval(() => { this.setState((state) => ({ message: state.msg1 + state.num++ + state.msg2 })); }, 1000); }
this.state
でmsg1
、num
、msg2
の3つの初期値を設定。num
は数値で三つ合わせると「羊が1匹」になる- 変数
count
でsetInterval()
のタイマー処理を設定 setInterval()
第1引数は無名関数でここに処理を書く
this.setState()
に関数を渡す。引数はstate
message
の値をstate
のmsg1
、num
に1を加算 、msg2
にするsetInterval()
の第2引数は時間で1000ミリ秒=1秒ごとに更新する
ブラウザ挙動
ブラウザを開くと 変わった!1秒ごとに羊を数えている!
App.js全体
import React from 'react'; import Img from './Img'; import './App.css'; class App extends React.Component { constructor(props) { super(props); this.state = { msg1: "羊が", num: 1, msg2: "匹" }; let count = setInterval(() => { this.setState((state) => ({ message: state.msg1 + state.num++ + state.msg2 })); }, 1000); } render() { return <div className="App"> <header className="App-header"> <div className="App-images"> <Img align="left" /> <Img align="center" /> <Img align="rignt" /> </div> <h1>初めてのステート</h1> <p>{this.state.message}</p> <p>{this.props.message}</p> </header> </div> } } export default App;
クリックイベントでステートを変更
イベント処理
次にクリックイベントでステートを変更して見る。
クリックイベントはコンポーネントにonClick
属性を入れる。
<タグ on○○={this.○}>
下記はJSXのときにやったイベント処理。この時はinputタグにonChange
属性を入れている。*1
※参考:【React】イベント属性を使ってみた(onChangeとonClick) - クモのようにコツコツと
App.js修正
今回はbuttonタグにonClick
属性を入れて見る所存。*2
App.jsのJSXレンダリング部分を修正
<button onClick={this.countUp}>数える!</button>
- buttonタグの
onClick
属性にcountUp
メソッドを設定
イベントを実行するためにはメソッドをthis
にバインドする必要がある。
this.○○ = this.○○.bind(this);
※参考:イベント処理 – React
コンストラクタ部分を修正
constructor(props) { super(props); this.state = { msg1: "羊が", num: 1, msg2: "匹", message: "羊が何匹?" }; this.countUp = this.countUp.bind(this); }
message
の初期値「羊が何匹?」を用意countUp
メソッドをthis
にバインドする
今回はクリックして初めてmessage
が表示される仕組みのため、message
の初期値が必要だった。
次にcountUp()
メソッドを設定する
countUp(e) { this.setState((state) => ({ num: state.num +1, message: state.msg1 + state.num + state.msg2 })); }
countUp()
の定義、引数はe
this.setState()
に関数を渡す。引数はstate
state
のnum
の数値を1つ増やす
message
をstate
のmsg1
、num
、msg2
にする。
ブラウザ挙動
ブラウザを見ると、初期値の「羊が何匹?」が表示された!
クリックすると「1匹」になる!
もう一回クリックすると「2匹」になる!
App.js全体
import React from 'react'; import Img from './Img'; import './App.css'; class App extends React.Component { constructor(props) { super(props); this.state = { msg1: "羊が", num: 1, msg2: "匹", message: "羊が何匹?" }; this.countUp = this.countUp.bind(this); } countUp(e) { this.setState((state) => ({ num: state.num +1, message: state.msg1 + state.num + state.msg2 })); } render() { return <div className="App"> <header className="App-header"> <div className="App-images"> <Img align="left" /> <Img align="center" /> <Img align="rignt" /> </div> <h1>初めてのステート</h1> <p>{this.state.message}</p> <button onClick={this.countUp}>数える!</button> </header> </div> } } export default App;
最後に
ステートの事始めとタイマー処理、イベント処理を体験しました。ブラウザの挙動自体はこれまでと同じような内容です。
しかしprops
ではコンポーネントの中に属性として値を入れていたので設定値がいろんなところに分散しそうです。それがステートで一元管理できるので、規模が大きくなるほどにメリットを感じることができそうです。
次回も引き続きステートを扱う予定です。それではまた!
※参考:Reactでやってみたことまとめ qiita.com