ReactのuseEffectの簡単サンプルまとめ

# はじめに

React のHooksのUseEffectのメモです。
ご指摘、感想、お待ちしています。。。

## 目次

1. まずはクラスで普通に書いてみる
2. 関数コンポーネントで書き換え
3. コンポーネントが削除される時は？


## 1. まずはクラスで普通に書いてみる

まずはクラスでチュートリアルにあるようなカウンターを書いてみます。

コンポーネントがマウントされた際に
`componentDidMount()`でカウントをコンソールログに出力しています。
`componentDidUpdate()`で更新が行われる度に同じくログを出力しています。

これを関数コンポーネントで書き換えてみましょう。

```jsx:ClassCounter
import React, { Component } from 'react'

class ClassCounter extends Component {
    constructor(props) {
        super(props)

        this.state = {
            count: 0
        }
    }

    componentDidMount() {
        console.log(`Class Counter Mount !! ${this.state.count}`)
    }
    componentDidUpdate() {
        console.log(`Class Counter Update !! ${this.state.count}`)
    }

    render() {
        const { count } = this.state
        return (
            <div>
                <button onClick={() => this.setState({ count: count + 1 })}>
                    Click {count} times
                </button>
            </div>
        )
    }
}


export default ClassCounter
```

## 2. 関数コンポーネントで書き換え

ポイントは`useEffect`の第2引数です。
空のリストの場合は、初回マウント時のみ
リストの中にstateを指定すると、そのstateが更新された時のみ
それぞれログが出力されるようになります。
また、リストには複数のstateを指定できます。
その場合は、どちらかが更新されるとログが出力されます。

```jsx:FunctionCounter
import React, { useState, useEffect } from 'react'

export default function FunctionCounter() {

    const [count, setCount] = useState(0)
    const [text, setText] = useState('')
    const [isShow, setShow] = useState(true)

    // レンダリングされた時にのみ実行
    useEffect(() => {
        console.log(`Function Component Mount`)
    }, [])

    // countが更新された時に実行
    useEffect(() => {
        console.log(`count state is updated ${count}`)
    }, [count])

    // textが更新された時に実行
    useEffect(() => {
        console.log(`text state is updated ${text}`)
    }, [text])

    // count または textが更新された時に実行
    useEffect(() => {
        console.log(`state text and count are updated count=${count} text=${text}`)
    }, [text, count])

    return (
        <div>
            <input type='text' value={text} onChange={e => setText(e.target.value)}></input>
            <button onClick={() => setCount(count + 1)}>
                Click {count} times
            </button>
        </div>
    )
}
```

## 3. コンポーネントが削除される時は？

ボタン操作で`ClassChildComponent`を表示を切り替えてみます。

```jsx:ClassComponent
import React, { Component } from 'react'
import ClassChildComponent from './ClassChildComponent'

class ClassComponent extends Component {
    constructor(props) {
        super(props)

        this.state = {
            isShow: false
        }
    }

    render() {
        const { isShow } = this.state
        return (
            <div>
                <button onClick={() => this.state.isShow ?
                    this.setState({ isShow: false }) : this.setState({ isShow: true })}>
                    isShow is {isShow}
                </button>
                {isShow && <ClassChildComponent />}
            </div>
        )
    }
}


export default ClassComponent
```

ClassChildComponentの方でコンポーネントが削除される際の
`componentWillUnmount()`を定義しています。
これをuseEffectで書き換えます。

```jsx:ClassChildComponent
import React, { Component } from 'react'

export default class ClassChildComponent extends Component {

    componentWillUnmount(){
        console.log('Child Class Component will Unmount !!')
    }

    render() {
        return (
            <div>
                <h3>Child Component</h3>
            </div>
        )
    }
}
```

まずは、同じように表示を切り替えるボタンのみのコンポーネントを準備します。

```jsx:FunctionComponent
import React, { useState} from 'react'
import FunctionChildComponent from './FunctionChildComponent'

export default function FunctionComponent() {

    const [isShow, setShow] = useState(false)

    return (
        <div>
            <button onClick={() => isShow? setShow(false) : setShow(true)}>
                isShow is {isShow}
            </button>
            {isShow && <FunctionChildComponent />}
        </div>
    )
}
```

呼び出すコンポーネントはこんな感じ
useEffectの中でreturn()を定義してあげると、componentWillUnmountと同じ動きになります。

```jsx:FunctionChildComponent
import React, {useEffect} from 'react'

export default function FunctionChildComponent() {

    useEffect(() => {
        return () => {
            console.log('Child Function Component will Unmount !!')
        };
    }, [])

    return (
        <div>
            <h3>Child Component</h3>
        </div>
    )
}
```