9
6

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

ゆる~い感じで全網羅するReact Hooks

Last updated at Posted at 2019-08-01

hooks 使うよ~

React Hooks

前提として React の知識があるといい!
Hooks は React の version16.8.0 (2019/02/06) で追加されたよ~
新しい技術ってだけでわくわくするね!!
https://ja.reactjs.org/docs/hooks-reference.html

Github に僕が書いた例文に使ってるソースコード置いておくから、良かったら見てね
typescript 使ってるから例文とちょっと違うと思うけど、処理は同じだよ
https://github.com/ajunajunajun/hooksWorld

import 文とか省いていくよ!
似た Hooks を並べてるから、場合によって使い分けてほしいな!

useState

class でいう State を使える奴

例:

const [count, setCount] = useState(0)

return <button onClick={() => setCount(count + 1)}>+1</button>

初期値0countとして定義されて、
setCount()で値変更できる~便利
boolean 型とか string 型とか 配列とか、なんでも入るよ!

useReducer

redux みたいに state 管理できる奴
これも useState みたく state が使える奴なんだけど、
コードが複雑になってきたらこっち使った方が分かりやすい!

例:

const reducer = (state, action) => {
  switch (action.type) {
    case 'increment':
      return { count: state.count + 1 }
    default:
      return state
  }
}

const ReducerComponent = () => {
  const [state, dispatch] = useReducer(reducer, 0)
  return
    <button onClick={() => dispatch({ type: 'increment' })}>+1</button>
}

useReducer(reducer,0)で、
state,dispatch を定義して使えるようにしてる!

dispatch({ type:'increment' })とかで、
reducer 内の action.type を指定して状態を弄ることが出来る~

redux もういらない?って思ったけど middleware 無いから非同期処理とかめんどそうだぁ

useContext

class でいう<Context.Consumer>を使える奴

例:

export const testContext = React.createContext({ context: 'contextdayo~' })
const ContextComponent = () => {
  const { context } = useContext(testContext)

  // 'contextdayo~'
  return console.log(context)
}

React.createContextで作られた context を持ってこれるよ!

useEffect

class でいう LifeCycle を使える奴

例 1:

useEffect(() => {
  console.log('a')
  return () => console.log('b')
}, [])

console.log('a')の位置が componentDidMount
console.log('b')の位置が componentWillUnMount

例 2:

useEffect(() => {
  console.log('a')
  return () => console.log('b')
}, [flag])

第二引数の配列の中に値入れると lifecycle が少し変わる!

console.log('a')の位置が componentDidMount,componentDidUpdate
console.log('b')の位置が componentWillUnMount(副作用時にも発火)

第二引数のflagの値の変化が発火条件で、

('a') -> flag変化 -> ('b') -> ('a') ってかんじ
return 無しでも使えるよ!

useLayoutEffect

↑ の useEffect とちょっと似てるよ!!

useEffect は描画を止めないで処理するから、
一瞬処理できてない物が写る可能性あるんだけど、
useLayoutEffect は描画止めるからその心配が無いよ!

基本 useEffect 使って、問題があればこっち使うのがいいらしい~

例:

useEffect(() => {
  console.log('a')
  return () => console.log('b')
}, [flag])

useLayoutEffect(() => {
  console.log('c')
}, [flag])

useEffect と useLayoutEffect を並べると先に useLayoutEffect が処理されるよ~

('c') -> ('a') -> flag変化 -> ('b') -> ('c') -> ('a') ってかんじ!!

useCallback

関数を保存するよ!

例 1:

const increment = useCallback(() => setCount(c => c + 1), [])

return <button onClick={increment}>+1</button>

再レンダリングのたびに、新しい関数が作られるのを防げて、
パフォーマンスが向上するよ!

例 2:

const increment = useCallback(() => setCount(c => c + num), [num])

return <button onClick={increment}>+1</button>

第二引数の配列の中に値入れておくと、その値が変わるたびに関数を作り直すよ
例 では1を変数にしておいて、後から増加分を変えれる様にしてる!

毎回更新されるような書き方だと逆にパフォーマンス落ちるよ!!
useCallback 自体の処理の方が重いからね!

useMemo

↑ の useCallback とちょっと似てるよ!!
useCallback は関数を保存するんだけど、
useMemo は関数の結果を保存するよ!前回と違ったら更新!

例:

// めっちゃ高価な計算
const dec_num_1 = useMemo(() => num - 1, [num])

// num - 1
return console.log(dec_num_1)

重たい計算があって、再レンダリングの度に繰り返したくないなら使おう!!
こんな例文みたいな超簡単な計算じゃ使っちゃだめだよ!
useMemo 自体の処理の方が重いからね!

useRef

あらゆる書き換え可能な値を保持しておけるよ!
コンポーネントの存在期間ずっと生存し続ける!!
代入しても state 変えるわけじゃないから再描画されない!

例:

const inputRef = useRef(null)

const focus_input = () => {
  inputRef.current.focus()
}

return (
  <button onClick={focus_input}>focus_input</button>
  <input ref={inputRef} type="text" />
)

useRef()の()内で初期値(ここでは null)設定して
<input ref={inputRef}>で input に持たせて
inputRef.current.focus()で focus 合わせる~みたいな

生存し続けるから、前回の値保持しといて何か処理したりできそう。
再描画されないから、描画に関係ない事に便利そうだし
色んな使い道がありそうだ~

useImperativeHandle

ref が使われた時に親コンポーネントに渡されるインスタンス値をカスタマイズ出来るよ!

なんでかは知らないけど、
ref を使った手続き的なコードはほとんどの場合に避けるべきです。
らしい~

例:

const MyInput = (props, ref) => {
  const myInputRef = useRef()
  useImperativeHandle(ref, () => ({
    setWaaaai() {
      myInputRef.current.value = 'Waaaaai'
    }
  }))

  return <input type="text" ref={myInputRef} />
}

export default forwardRef(MyInput)
const inputRef = useRef()

<MyInput ref={inputRef} />
<button
  onClick={() => { inputRef.current.setWaaaai() }}
>
  Waaaai
</button>

子供の MyInput で作った setWaaaai()を親で使える感じ、ふ~ん

Custom Hooks

規則に合わせて自分で Hooks を作れるよ
規則って?

  • フックを呼び出すのはトップレベルのみ
  • フックを呼び出すのは React の関数内のみ
  • 名前が use で始まる

このみっつ

例:

const useJudgeCount = (count) => {
  const [isZero, setBool] = useState(false)
  useEffect(() => {
    count === 0 ? setBool(true) : setBool(false)
  }, [count])

  return isZero
}

export default useJudgeCount
const isZero = useJudgeCount(count)

return
  {isZero ? <p>0だよ</p> : <p>0じゃないよ </p>}

適当に count が 0 か否かを教えてくれる奴作ってみた!
色々機能ごとにファイル分けれるから綺麗に書けそう~

useDebugValue

ReactDevTools で CustomHooks のラベルを表示できるよ

さっき作った useJudgeCount の中に
useDebugValue(isZero)
って書くだけで、ReactDevTools でその値が確認できる!!便利!!!

まとめ

最近Reactを学び始めたのですが、FunctionalComponentとHooks使いこなせば色々出来そうだと感じました。Hooks自体今年に出た技術なので、これからのHooksを追っていくのも楽しそうです。

拙い文章でしたが、読んでくださりありがとうございました。

9
6
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
9
6

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?