Reactとは
Metaが開発したJavaScriptのライブラリ
以下の3つの特徴がある。
- Declarative(宣言的)
- Component-Base(コンポーネントベース)
- Learn Once, Write Anywhere(一度の学びでなんでも書ける)
JSXとは
JavaScriptでHTML文を書けるように拡張したもののこと。
JavaScriptの拡張構文がJSXなのに対して、TypeScriptでHTML文を書けるように拡張したものがTSX。
TSX内でJavaScriptの構文を適応したい場合は{}で囲うことで使うことができる。
コンポーネントとは
見た目と振る舞いをセットにしたUI部品の最小単位のこと。
Reactには関数コンポーネントとクラスコンポーネントがあったがHooksの登場で関数コンポーネントを使うのが一般的になった。
Contextとは
React Hooks
ルール
Hookを呼び出すのはReactの関数内のみ。
useState
useStateはコンポーネントの状態を管理するためのHook。
const [状態を表す変数,状態を変化させる関数名] = useState(状態の初期値)
const [count, setCount] = useState(0)
// countの値を更新
setCount(count+1)
// またはこっち
setCount((preCount)=>preCount+1)
状態を変化させる関数の名前はset変数名とすることが通例。
useStateでオブジェクトや配列を扱う場合はスプレッド構文({...})を用いて展開し、変更点を追加で記述する必要がある。
useStateの場合、更新関数に渡された値は既存の状態にマージするのではなく、新たな状態として置換してしまうため、元のオブジェクトや配列を展開して前回の状態を残す必要がある。
const [obj, setObj] = useState({})
// 値の更新
setObj({...obj,追加する値})
const [arr, setArr] = useState([])
// 値の更新
setArr([...arr,追加する値])
useReducer
useStateと同様にコンポーネントの状態を管理するHook。
useStateはuseReducerに内部実装されている。
const [state, dispatch] = useReducer(reducer,初期値)
stateは状態を表す変数で、stateの更新関数がreducer。
dispatchはreducerを呼び出す関数のこと。
dispatch(action)
reducerの呼び出しにはdispatchにオブジェクトactoinを引数に渡すことで、更新関数のreducerが発火。
const reducer = (state, action) => {
// actionに応じた処理内容
return 次のstateの値
}
reducerに引き渡される引数はコンポーネントの状態を示すstate、dispatchから渡されるオブジェクトactionがある。
action内の指定のプロパティに対しての処理をswitch文などで書いていく。
useStateとuseReducerの使い分け
useStateとuseReducerは状態を更新するという意味では役割が似ている。以下のような条件で使い分けると可読性の面でも優れる。
| 項目 | useState | useReducer |
|---|---|---|
| 扱うステートの型 | Number, String, Boolean | Object, Array |
| 関連するステートを扱う | × | ◯ |
| ローカルorグローバル | ローカル | グローバル useContext()と併用する |
useEffect
DOMの更新後に呼び出したい処理を指定することができるHook。
useEffect(()={
//処理内容
},[状態変化を監視するステート名])
DOM更新後に実行されるためuseEffectが呼び出されたときは適切にDOMの更新が行われたことを示す。
※初回render時と、指定したステートがあれば、そのステートが更新されるごとに実行される。
// ステートの設定
const [count, setCount] = useState(0)
const [value, setValue] = useState('')
// ページタイトルを変更
useEffect(()={
document.title = `{count}`
})
この場合、ステートを指定していないためuseEffectは以下の状況で実行される。
- 初回
render時 -
countが更新された時 -
valueが更新された時
処理内容的にはcountが更新された時だけuseEffectが発火すれば問題ないので、ステートを指定して、発火回数を減らすことができる。
const [count, setCount] = useState(0)
const [value, setValue] = useState('')
// ページタイトルを変更
useEffect(()={
document.title = `{count}`
},[count])
useEffectの第二引数の配列の中に監視したいステートを指定することでそのステートが更新された時のみ発火し、それ以外は無視するということができる。
この場合、useEffectは以下の状況で実行される。
- 初回
render時 -
countが更新された時
このようにすることで、valueが更新された場合、発火を無視することができる。
また第二引数に空の配列([])を指定した場合は処理を初回render時のみ実行されるようにすることができる。
const [count, setCount] = useState(0)
const [value, setValue] = useState('')
// ページタイトルを変更
useEffect(()={
document.title = `{count}`
},[])
この場合初回render時のみ発火されるので、ページタイトルは0のままとなる。
またuseEffectで指定した関数にreturnを設定することで、そのコンポーネントがDOMから削除(アンマウント)された時に実行する処理を指定することができる。
useEffect(()={
// マウスが動いた時の処理を追加
window.addEventListener('mousemove',実行される関数)
return () => {
// アンマウント時に実行される処理
// 登録した処理を削除
window.removeEventListener('mousemove',実行される関数)
}
})
わかりやすい記事
useContext
コンポーネントのデータを親コンポーネントから橋渡ししなくても扱えるようにするHook。
書き方は以下の通り。
import {createContext} from 'react'
import {ComponentC} from './component/ComponentC'
export const UserContext = createContext()
export function App() {
const [user, setUser] = useState({name:'yamada',age:32})
return (
<div className="App">
<UserContext.Provider value={user}>
<ComponentC />
</UserContext.Provider>
</div>
);
}
渡したいコンポーネントを作成したContextのProviderであるUserContext.Providerで囲む。
この時valueに引き渡したい変数を渡す。
この時作成したContextは他のファイルで用いるためexportしている。
import React, { useContext } from 'react'
import {UserContext} from '../App'
export function ComponentF(){
const user = useContext(UserContext)
return (
<div>
{user.name}
</div>
)
}
※ComponentFはComponentCに内包されているとする。
useContextを用いて、渡されたContextを受け取り、変数に入れることができる。
以降はそのスコープ内で変数を用いて値を使用することができる。
useRef
要素への参照を行うHook。
useStateのように値の保持を行うことができるが、useStateとは違い値が更新されても再レンダーされないのが特徴。
const ref = useRef(初期値)
useRefはコンポーネントのトップレベルで呼び出して変数を宣言する必要がある。
宣言時currentプロパティに初期値が入っているオブジェクトを返す。
主に値を参照する場合、DOM操作を行う場合に用いられる。
値を参照する場合
参照したい値をuseRefで定義し、更新にはcurrentプロパティを指定して再代入することでレンダリングはそのままで値の更新が行うことができる。
// 参照したい値の定義
const count = useRef(0)
// 値の更新
count.current = 1
DOM操作を行う場合
操作したいDOMノードのJSXに定義したrefオブジェクトを引き渡す。
引き渡されたDOMはcurrentに格納されるので、currentプロパティを指定して、通常のDOM操作を行う。
// useRefの定義
const inputDom = useRef(null)
// DOMの指定(JSX内)
return <input ref={inputDom} />
// DOMの操作(入力欄にフォーカスする)
inputDom.current.focus()