Open2

Hooksまとめ

どるあがどるあが

Hooksまとめ

  • useState
  • useEffect
  • useContext
  • useRef
  • useReducer

準備

$ npm create vite@latest

reactを選択

$ . code

VSCODEが立ちあがる

$ npm run dev

実行

useState

状態の変化が起こったときにレンダリングを行う
Reactは仮想DOMの差分だけを見ており、差分が発生したら変更点だけ
リアルDOMに反映する

App.js
export const App = () => {
  const [count, setCount] = useState(0)

  const handleClick = () => {
    setCount(count + 1);
  }

  return (
    <div className="App">
      <h1>UseState</h1>
      <p>状態の変化が起こったときにレンダリングを行う</p>
      <button onClick={handleClick} >+</button>
      <p>{count}</p>
    </div>
  )

useEffect

発火のタイミングを指定する
useEffect(コールバック関数,配列)

  1. 配列が空だとコンポーネントのマウント時に一回呼ばれる
  2. []の中に変数を入れると、入れた変数が変更された時に発火する

ではこのような場合は…?

  useEffect(() => {
    console.log("Hello Hooks");
    setCount(count + 1);
  }, [count])


えらいことになる。setCountがcountを変更してさらにuseEffectが呼ばれて、無限ループが発生するので気を付けよう。

useContext

staticグローバル変数みたいなやつ

まずは全体で使いたいデータを用意しよう

const myInfo = {
  name: "dollaga",
  age: 30,
}

そしてcreateContextでContextを用意します

export const MyInfoContext = createContext(myInfo);

最後にProviderを使い全体を囲む

main.jsx
ReactDOM.createRoot(document.getElementById('root')).render(
  <MyInfoContext.Provider value={myInfo}>
    <React.StrictMode>
      <App />
    </React.StrictMode>
  </MyInfoContext.Provider>
  
)

使いたい要素をpropsのvalueで渡す必要があるらしい

では使う側はどうか?

App.jsx
  export const App = () => {
  const [count, setCount] = useState(0)
  const myInfo = useContext(MyInfoContext)

  ~
  return (
    <div className="App">
      <h1>useContext</h1>
      <p>staticグローバル変数みたいなやつ</p>
      <p>{myInfo.name}</p>
      <p>{myInfo.age}</p>
    </div>
  )

というわけでmain.jsxで定義したMyInfoをAppに直接渡すことができました

どんな場合に必要か?
ユーザーのログイン情報などどのページでも使う情報

useRef

指定したhtmlのタグを参照する(reference)

  const ref = useRef();

  const handleRef = () => {
    console.log(ref);
  }

  ~
  return (
    <div className="App">
      <h1>useRef</h1>
      <input type="text" ref={ref} />
      <button onClick={handleRef}>UseRef</button>
    </div>
  )

こうしてボタンを押すと、様々なinputタグの情報をみることが出来る

valueの中身を見たい時などに活用できる

const handleRef = () => {
    console.log(ref.current.value); //valueの中身
  }

useReducer

あんまり使わない??

考え方が難しい割には使わなくても実現できるなあ

Reducer
const reducer = (state, action) => {
  switch (action.type) {
    case "increment":
      return state + 1;
    case "decrement":
      return state - 1;
    default:
      return state;
  }
};

~

  const [state, dispatch] = useReducer(reducer, 0);

~
      <h1>useReducer</h1>
      <p>カウント:{state}</p>
      <button onClick={() => dispatch({type: "increment"})}>+</button>
      <button onClick={() => dispatch({type: "decrement"})}>-</button>

useMemo

パフォーマンスをチューニングするためのHooks
ブラウザのメモリに保存=メモ化
重い処理の時に使うけど、どんなものが重い処理か定義できないので、
開発しながら考えよう
つまり、最初からは使えない...かもしれない(shincodeさん曰く)

なんでもかんでも使えばいいかというと、そういうわけでもない
(メモリリークしちゃう)

useCallback

callback関数のメモ化

useMemoと使い方は同じ

つまり、あんまり使わないらしい笑

ちょっと検討の価値があるなあ

どるあがどるあが

カスタムフック

今回はローカルストレージに年齢を保存するHooksだぞ
これを参考にいろいろ作れそうだな

useLocalStorage.jsx

import React, { useEffect, useState } from 'react'

export const useLocalStorage = (key, defaultValue) => {
  const [value, setValue] = useState(() => {
    const jsonValue = window.localStorage.getItem(key);
    if(jsonValue !== null) return JSON.parse(jsonValue);

    return defaultValue
  })

  useEffect(() => {
    window.localStorage.setItem(key, JSON.stringify(value))
  }, [value, setValue]);

  return [value, setValue];
}