React useState useEffect使い方
React useState使い方
なぜ使うか
A: Class, super, this... と書くより短くかけるから
code
これを参考にした
まずcreate-react-app で作ったprojectに
import React, { useState } from 'react';
で, {useState }を追加
アローfnで入れ物を書く.
const App = props => { ....... return ( <div> </div> ) }
ここに
stateの初期化
switch関数などの関数
personsを表示するreturn ( 関数をonClickにtriggerしたりもここに入れる )
を書いていく.
const [personsState, setPersonsState] = useState({ persons: [ {name: 'Max', age: 28,}, {name: 'Stef', age: 16,}, ], otherState: 'some other val' }); console.log(personsState);
これでpersonsStateというstateの中に
personsの配列とotherStateという文字列が入り
setPersonsStateに何かを渡すことでこのpersonsStateは
書き換わり,stateなのでその瞬間returnの値が再描画される.
まずはreturnのdivの中に現在のpersonsStateをmapする
{personsState.persons.map(person => ( <div key={person.age}> <h1>{person.name}</h1> <h1>{person.age}</h1> </div> ))} <button onClick= {switchNameHandler}>switch</button>
ついでにbtnに書き換えswitchのfuncを噛ませる
これでpersonsState.personsの値が描画された
const switchNameHandler = () => { setPersonsState({ persons: [ {name: 'Maximum', age: 100,}, {name: 'Stephanie', age: 0,}, ] }) }
さっきのbtnにonClickで紐付けたfuncの中身をかく.
ただpersonsの中身をおじいさんと赤ん坊に書き換えるだけのだ.
personsという同じ名前の別の中身の配列を渡す.
これでclickすると切り替わる
onClickした時にswitch関数が発動して,
setPersonsStateにpersonsの配列を入れただけだが,
これで画面まで再描画されてる.stateが書き変わったからだ.
次はuseEffectを実際に動かす.
useEffect
useEffect(fn, []) で書く。
公式のサンプルのコードはこれだ
import React, { useState, useEffect } from 'react'; function Example() { const [count, setCount] = useState(0); // Similar to componentDidMount and componentDidUpdate: useEffect(() => { // Update the document title using the browser API document.title = `You clicked ${count} times`; }); return ( <div> <p>You clicked {count} times</p> <button onClick={() => setCount(count + 1)}> Click me </button> </div> ); }
同じようにさっきの人を表示するコードにも追加してみる
- import React, { useState, useEffect, } from 'react';
でuseEffectも読み込んで
useEffect( ()=> { console.table(personsState.persons) })
これをreturnの上に追加する
すると
useEffectに書いていた関数が変更時に実行されている.
これがフックされた副作用というらしい.
ボタンを連打してもhtmlは書き変わるのがわからないが,
stateは上書きされ続けるので,useEffectは反応して,
押した数だけconsoleにpersonsのtableが出る.
useEffect( ()=> { console.table(personsState.persons) }, [personsState]);
こうすれば [] 無いの値が動いた時にしかEffectが起きないので,
パフォーマンスが向上するらしい.
これは別のstateをやってみて相互検証する必要があるな
とりあえずuseEffectの中に書いておけばstateが動いた時に更新される!!よし!
以下がuseState, Effect動作確認ようコード
import React, { useState, useEffect, } from 'react'; import './App.css'; const App = props => { const [personsState, setPersonsState] = useState({ persons: [ {name: 'Max', age: 28,}, {name: 'Stef', age: 16,}, ], otherState: 'some other val' }); const switchNameHandler = () => { setPersonsState({ persons: [ {name: 'Maximum', age: 100,}, {name: 'Stephanie', age: 0,}, ] }) } useEffect( ()=> { console.table(personsState.persons) }, [personsState]); return ( <div> {personsState.persons.map(person => ( <div key={person.age}> <h1>{person.name}</h1> <h1>{person.age}</h1> </div> ))} <button onClick= {switchNameHandler}>switch</button> </div> ) } export default App;
https://qiita.com/k-penguin-sato/items/9373d87c57da3b74a9e6
によると
実際はuseEffectの第2引数を空にすると、FCのstate, propsのうちいずれかが更新される度にuseEffectのbodyが走るようになる為危険です。その為、通常第2引数を空にすることはありません。
第2引数ナシにするとやばいらしい……
ただ空の配列ならマウント?が起こる度にしか更新されないから安全?stateのみに反応するようになるってことかな?
引数渡せばそれが変化した時のみuseEffectの中身が実行されるから、とにかくそうするべきらしい。
マウントとアンマウントがわからなくなったので調べていた.
useHogeとMount
教えていただいたのだが.
(引数が)なしは毎回実行 空配列は常に等しいのでマウント時のみ実行 ... まずrenderはこれまでのクラスインターフェイスでもマウントされた時以外も実行される propsが変更された時やsetStateした時 それと同じで引数の変更やuseStateでのsetStateで関数は再実行される 毎回実行にするとそのたびにuseEffect内部関数の実行が行われる
とのことで[]だとMount のみ実行で 引数なしだとUpdateでも実行されるらしい.
この記事によると多分DOMが生成される時がMount
stateが変わる時がUpdate, 全部終わってUnMount?になる
LifeCycle
そもそもLifecycleの理解が必要だった.
これによると
class内最初のrender()がMount 2回目以降のrender()がUpdate DOMからの削除がUnmount
整理すると
Mount: DOMにNodeが追加された時.ReactDOM.render
が発動した時?
一番最初に描画された時?renderをtriggerする
Update: stateに変化が応じた時に起きる.renderをtriggerする.
Render: Mount, Updateが起こった時にstate, propsを読み込んでまた行われる
useEffectはそのcomponentでUpdateが起こった時に計算される式である.
propsが変化した場合にも起こるらしい
(間違ってたら教えてください)
結論
やはり理論ではピンとこないからうまく動かすしかない!w
名前からしてわかりやすいcomponentWillUpdate...とかにcllつけて
出してサンプルコード書いてる時に試していくしかないな,
そのために長いけどClass記法,全く書かないわけには行かないね....