KAEDE Hack blog

JavaScript 中心に ライブラリなどの使い方を解説する技術ブログ。

React useState useEffect使い方

React useState使い方

なぜ使うか

A: Class, super, this... と書くより短くかけるから

code

www.udemy.com

これを参考にした

まず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を噛ませる

f:id:kei_s_lifehack:20200528055336p:plain

これでpersonsState.personsの値が描画された

const switchNameHandler = () => { 
  setPersonsState({               
    persons: [                    
    {name: 'Maximum', age: 100,}, 
    {name: 'Stephanie', age: 0,}, 
    ]                             
  })                              
}                                 

さっきのbtnにonClickで紐付けたfuncの中身をかく.

ただpersonsの中身をおじいさんと赤ん坊に書き換えるだけのだ.

personsという同じ名前の別の中身の配列を渡す.

これでclickすると切り替わる

f:id:kei_s_lifehack:20200528055716p:plain

onClickした時にswitch関数が発動して,

setPersonsStateにpersonsの配列を入れただけだが,

これで画面まで再描画されてる.stateが書き変わったからだ.

次はuseEffectを実際に動かす.


useEffect

useEffect(fn, []) で書く。

公式のサンプルのコードはこれだ

reactjs.org

 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の上に追加する

すると

f:id:kei_s_lifehack:20200528063343p:plain

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でも実行されるらしい.

codezine.jp

f:id:kei_s_lifehack:20200528225759p:plain

この記事によると多分DOMが生成される時がMount

stateが変わる時がUpdate, 全部終わってUnMount?になる

LifeCycle

そもそもLifecycleの理解が必要だった.

qiita.com

これによると

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記法,全く書かないわけには行かないね....