【React】 hook を使う
噂のhookを使ってみる。今更な気もするけど。ここを見ると何とかできそう。
- 準備
- hookを記述
- serve
- useEffect
- useContext
- createContext()
- 実装
- useReducer
- useMemoとuseCallback
- メモ化
- useMemo
- useCallback
- 参考文献
準備
テンプレ作成。
~/development
❯ create-react-app try-hook
~/development 34s
❯ cd try-hook
hookを記述
App.jsにhookを書いてみる。
import React, { useState } from 'react'; function App() { const [count, setCount] = useState(0); return ( <div> <p>You clicked {count} times</p> <button onClick={() => setCount(count + 1)}> Click me </button> </div> ); } export default App;
serve
yarnを使ってserveする。
yarn start
驚くほど、簡単に表示できた。
useEffect
これを使うと、click後に何かを仕込むことができると思ってた。
ボタンを押したら文字を赤くできるか試してみた。
以下の状態だと、初めから赤くなっている。なんで??
import React, { useState, useEffect } from 'react'; function App() { const [count, setCount] = useState(0); useEffect(() => { const elm = document.querySelector(".text"); elm.style.color = "red"; }); return ( <div> <p className="text">You clicked {count} times</p> <button onClick={() => setCount(count + 1)}> Click me </button> </div> ); } export default App;
デフォルトでは副作用関数はレンダーが終了した後に毎回動作します
らしい。
もしかして、vueのwatchやcomputerに近い?
以下のように書いたら無限にcountが増加し始めた。
import React, { useState, useEffect } from 'react'; function App() { const [count, setCount] = useState(0); useEffect( () => { setCount(count + 1); }, [count] ); return ( <div> <p className="text">You clicked {count} times</p> <button onClick={() => setCount(count + 1)}> Click me </button> </div> ); } export default App;
useEffectに対して、もっと調べた方がよさそう。
useContext
これ何に使うんだろう。
const value = useContext(MyContext);
サンプルで1行載ってた。
つまりどういうことなんだ?
調べてみる。
createContext()
こういうメソッドがあるらしい。useContextはこれをhookとして使えるようにしたものみたい。バケツリレーを回避するアプローチなのかな。 親側で定義したものを間を意識せず子供側で利用できるみたい。これは、好きかって親で定義してしまって、子供でも好き勝手使ってしまえるのでは? 重複して定義してしまったらどうなるんだろうか?いろいろ疑問が出る。
しかし、たまに同じデータがツリー内の異なるネスト階層にある多くのコンポーネントからアクセス可能であることが必要となります。
これを読むと、本当に限られたところでしか使うべきではないってことなのかな。よくよく読んでくと重複はできないようになっているっぽい。それに、
ツリー内の最も近い上位の一致する Provider から現在のコンテクストの値を読み取ります。
これのおかげで、好き勝手にcontextを使うみたいな感じではないかな。
実装
useContextを使ってみる。
import React, { useContext } from 'react'; const ContextA = React.createContext(); const ContextB = React.createContext(); function App() { return ( <ContextA.Provider value={10}> <ContextB.Provider value={20}> <Preview /> </ContextB.Provider> </ContextA.Provider> ); } function Preview() { const valueA = useContext(ContextA); const valueB = useContext(ContextB); return <p>{valueA} + {valueB}</p> } export default App;
useReducer
reduxを簡単に実装できるのかな?調べながら書いてみた。
import React, { useContext, useReducer } from 'react'; const initialState = {count: 0}; function reducer(state, action) { switch (action.type) { case 'increment': return {count: state.count + 1}; case 'decrement': return {count: state.count - 1}; default: throw new Error(); } } const CountDispatch = React.createContext(null); function App() { const [state, dispatch] = useReducer(reducer, initialState); return ( <> Count: {state.count} <CountDispatch.Provider value={dispatch}> <IncrementButton /> <DecrementButton /> </CountDispatch.Provider> </> ); } function IncrementButton() { const dispatch = useContext(CountDispatch); function handleClick() { dispatch({type: 'increment'}); } return <button onClick={handleClick}>+ 1</button> } function DecrementButton() { const dispatch = useContext(CountDispatch); function handleClick() { dispatch({type: 'decrement'}); } return <button onClick={handleClick}>- 1</button> } export default App;
これで無事に動いた。useContextとuseReducerを合わせながら書くといいのかもしれない。知らんけど。この辺りの知見が全く無いので今後調べてブログに書きたい。
useMemoとuseCallback
この2つは結構使われているのかな。なかなか簡単に学べるものでは無い気がする。主にはメモ化するときに使うみたい。でもメモ化ってなんだろうか?
メモ化
wikiに書いてあった。
関数のキャッシュのようなものなのかな。
useMemo
せっかくだから使ってみる。正しく使えているのかはわからないけど。
import React, { useState, useMemo } from 'react'; function App() { const [count, setCount] = useState(0); const value = useMemo(() => { return Math.sqrt(10000000); }, []); return ( <div> <p>{ value }</p> <p>{ count }</p> <button onClick={() => { setCount(count + 1); }}>+ 1</button> </div> ) } export default App;
こんな感じにすると、ボタンが押されてもvalueが再計算されない。つまりメモ化できてる???
useCallback
これも使ってみる。同じく正しく使えているのかはわからないけど。
import React, { useState, useCallback } from 'react'; function App() { const [count, setCount] = useState(0); const click = useCallback(() => { return setCount(c => c + 1) }, []); return ( <div> <p>{ count }</p> <button onClick={click}>+ 1 memo</button> </div> ) } export default App;
参考文献
- React – A JavaScript library for building user interfaces,入手先 https://reactjs.org/
- useContextのしくみ - Qiita,入手先 https://reactjs.org/https://qiita.com/ossan-engineer/items/8f2640e4ee053b353943