Reactのバケツリレーをやめるには？  

## バケツリレーをやめる男のはなし

### ＜ ある昼下がり ＞

なになに..  

> Fugaボタンをクリックすると、Fugaが1増える。  
Mogeは常にFugaよりも1大きくて、  
Mugaは常にMogaの3倍である。  

なるほどなぁ..  

やとすれば、
Fugaボタンを一定回数クリックしたときの、MogeとMugaを一瞬にして求められたらうれしいなぁ...  

Reactの勉強も兼ねてそうゆうのだれか作ってくれへんかなぁ...  


[![Edit vigorous-silence-5dodd](https://codesandbox.io/static/img/play-codesandbox.svg)](https://codesandbox.io/s/vigorous-silence-5dodd?fontsize=14&hidenavigation=1&theme=dark)

こんなやつ...  

...  

...  

...  

...  


...あぁ、自分でやったらええんか。
その方が勉強になるし...

### ＜ つぎの日 ＞

できた！  

```
src
├── components
│   ├── App.js
│   ├── Fuga.js
│   ├── Hoge.js
│   ├── Moge.js
│   └── Muga.js
└── index.js
```

componentsディレクトリがこんな風になってて...  

```jsx:App.js
import React,{useState} from 'react'
import Fuga from './Fuga'
import Hoge from './Hoge'

const App = () => {
  const [count, setCount] = useState(0)
  const moge = count + 1
  const muga = moge * 3
  return (
    <>
      <Fuga count={count} handleClick={() => setCount(count + 1)}/>
      <Hoge moge={moge} muga={muga} />
    </>
  )
}

export default App
```

最上位のコンポーネント`App.js`がでFugaコンポーネントとHogeコンポーネントを使ってて...  


```jsx:Fuga.js
import React from 'react'

const Fuga = ({count,handleClick}) => {
  return (
    <section>
      <h1>Fugaについて</h1>
      <p>ボタンを押すと、Fugaが1大きくなる。</p>
      <button onClick={handleClick}>Fuga</button> Fuga : {count}
    </section>
  )
}

export default Fuga
```

Appコンポーネントの子コンポーネントであるFugaコンポーネントに、FugaボタンとFugaの値を表示させて...  

```jsx:Hoge.js
import React from 'react'
import Moge from './Moge'
import Muga from './Muga'

const Hoge = ({moge,muga}) => {
  return (
    <section>
      <h1>MogeとMugaについて</h1>
      <p>MogeはFugaより1大きく、MugaはMogaの3倍である。</p>
      <Moge count={moge} />
      <Muga count={muga} />
    </section>
  )
}

export default Hoge
```

HogeコンポーネントにMogeとMugaのコンポーネントを置く...  

```jsx:Muga.js
import React from 'react'

const Moge = ({count}) => {
  return (
    <p> Moge : {count} </p>
  )
}

export default Moge
```

Mugaコンポーネントで`muga`を受け取り、Mugaの値を表示する...  

```jsx:Moge.js
import React from 'react'

const Muga = ({count}) => {
  return (
    <p> Muga : {count} </p>
  )
}

export default Muga
```
Mogeコンポーネントで`moge`を受け取り、Mogeの値を表示させる...  

...  

...  

...できた。  

...  

...  

...  

...でも  

...なんか、このHogeコンポーネントのここ...  

```jsx:Hoge.js
const Hoge = ({moge,muga}) => {
  return (
    <section>
      <h1>MogeとMugaについて</h1>
      <p>MogeはFugaより1大きく、MugaはMogaの3倍である。</p>
      <Moge count={moge} />
      <Muga count={muga} />
    </section>
  )
}
```

Hogeコンポーネントでは`moge`も`muga`も使わへんのに、ただ受け取って、次のMogeとMugaのコンポーネントに渡してるだけやな...  

今回は別にまあええけど、このFugaプロジェクトが波に乗ってもっと大きくなったら、このままやと大変になるな...  

今のうちになんかええ方法考えとこ...  

### ＜ その日の晩 ＞
  
「*konbanwa...*」  

はっ！！！
だれや！？  


「*createContextcreateContextcreateContextcreateContextcreateContextcreateContextcreateContextcreateContextcreateContextcreateContextcreateContextcreateContextcreateContextcreateContextcreateContextcreateContextcreateContextcreateContextcreateContextcreateContextcreateContextcreateContextcreateContextcreateContextcreateContextcreateContextcreateContextcreateContextcreateContextcreateContext...*」  


やめろっ！！！  

「*ProviderConsumerProviderConsumerProviderConsumerProviderConsumerProviderConsumerProviderConsumerProviderConsumerProviderConsumerProviderConsumerProviderConsumerProviderConsumerProviderConsumerProviderConsumerProviderConsumerProviderConsumerProviderConsumerProviderConsumerProviderConsumerProviderConsumer...*」  

やめてっっっ！！
そこだけはっ！！！！
うわ〜〜〜〜〜〜〜〜っ！！！！！！！

### ＜ つぎの日の朝 ＞

ん...?
あぁ...なんや...夢か...
なんやったっけ...?  

あぁ...せやせや、コンテキストがどうたらこうたらで...  

...ってことは...
contextsディレクトリ作って、そこに`AppContext.js`作って...  

```
src
├── components
│   ├── App.js
│   ├── Fuga.js
│   ├── Hoge.js
│   ├── Moge.js
│   └── Muga.js
├── contexts
│   └── AppContext.js
└── index.js
```

そしたらこんな感じか...  

なんかProviderやらConsumerやらが云々カンヌン言っとったな...  

```AppContext.js
import {createContext} from 'react'

const AppContext = createContext()

export default AppContext
```

contextsディレクトリに置いた`AppContext.js`をこう書いといて...  

```jsx:App.js
import AppContext from '../contexts/AppContext'
```

Appコンポーネントで`AppContext.js`読み込んで...  

```jsx:App.js
return (
  <>
    <AppContext.Provider value={{count,moge,muga}}>
      <Fuga count={count} handleClick={() => setCount(count + 1)}/>
      <Hoge moge={moge} muga={muga} />
    </AppContext.Provider>
  </>
)
```
returnの直下のDOMをProviderでラップして...  
そのProviderにvalueとして`count`と`moge`と`muga`を渡す...  

それから...  

```jsx:Moge.js
import React from 'react'
import AppContext from '../contexts/AppContext'

const Moge = () => {
  return (
    <p>
      Moge :
      <AppContext.Consumer>
        {value => <> {value.moge}</>}
      </AppContext.Consumer>
    </p>
  )
}

export default Moge
```
Mogeコンポーネントでも`AppContext`を読み込んで...  
こっちはConsumerを使う...  
そしたら、Consumer中では`value`の`moge`が受け取れる...    

```jsx:Muga.js
import React from 'react'
import AppContext from '../contexts/AppContext'

const Muga = () => {
  return (
    <p>
      Muga :
      <AppContext.Consumer>
        { value => <> {value.muga}</> }
      </AppContext.Consumer>
     </p>
  )
}

export default Muga
```

Mugaコンポーネントもおんなじようにして...  

```jsx:Hoge.js
import React from 'react'
import Moge from './Moge'
import Muga from './Muga'

const Hoge = () => {
  return (
    <section>
      <h1>MogeとMugaについて</h1>
      <p>MogeはFugaより1大きく、MugaはMogaの3倍である。</p>
      <Moge />
      <Muga />
    </section>
  )
}

export default Hoge
```

これでHogeコンポーネントは無駄に`moge`やら`muga`やら受け取らんでもええようになったな...  
できたな...  

...  

...  

...  

...  

... でもなー  

なんかなー...  

```jsx:Moge.js
<AppContext.Consumer>
  {value => <> {value.moge}</>}
</AppContext.Consumer>
```

この部分なんかスッキリせえへんねんな...  

他になんかないんかな...  

また時間あるとき考えとこ...  

### ＜ その日の晩 ＞

「maido...」  


ん...?
またか？
だからだれやねん...

「*useContextuseContextuseContextuseContextuseContextuseContextuseContextuseContextuseContextuseContextuseContextuseContextuseContextuseContextuseContextuseContextuseContextuseContextuseContextuseContextuseContextuseContextuseContextuseContext*」  

うゎぁぁぁぁぁーーーーーーー!!!!!!!!  

### ＜ 次の日の朝 ＞

また変な夢やったな...  

今回もなんか言っとったな...
えーと... なんやっけ...
`useContext`がなんちゃらかんちゃらやったかな...  

```jsx:Moge.js
import React, {useContext} from 'react'
import AppContext from '../contexts/AppContext'

const Moge = () => {
  const value = useContext(AppContext)
  return <p>Moge : {value.moge}</p>
}

export default Moge
```

`react`から`useContext`を読み込んで...
`useContext`の引数に`appContext`を渡して`value`を受け取る...
これでよし...    

```jsx:Muga.js
import React, {useContext} from 'react'
import AppContext from '../contexts/AppContext'

const Muga = () => {
  const value = useContext(AppContext)
  return <p> Muga : {value.muga} </p>
}

export default Muga
```

ほんでから、Mugaコンポーネントもおんなじように書く...
うん、こっちのほうが簡単で見やすいわ...  

アイツええヤツやったな...  

**＜ おわり ＞**

---

...そもそもFugaボタンってなんやねん！！！

## 参考

- [Udemy ~React Hooks 入門 - Hooksと Redux を組み合わせて最新のフロントエンド状態管理手法を習得しよう！~](https://www.udemy.com/course/react-hooks-101/) ([はむさん プログラミングおじさん](https://www.udemy.com/user/76100880-5658-4a37-be77-5525d39a4726/))
- [フック API リファレンス](https://ja.reactjs.org/docs/hooks-reference.html)
- [コンテクスト](https://ja.reactjs.org/docs/context.html)