環境
- windows10
- DockerDesktop for Win 3.5.x
- node 16.13.1
- npm 8.1.2
- TypeScript 4.5
- React 17.0.1
- Next.js 12.0.7
- Recoil 0.5.2
- VsCode
- gitbash 2.32.0.1
useContext
- Reduxなどの状態管理storeを使用せず、propsのバケツリレーを回避できるHooksのひとつ
- 単なる親→子へ渡すくらいであれば、propsでOKだが、親→子→孫などになってくると、ややこしくなる。useContextは、孫やその子孫要素に渡す場合にその効力を発揮する
渡す側
- createContextをimport
- createContextからpropsを渡す対象のコンポーネントをラップするコンポーネントを生成し、exportする
- ラップしつつ、valueでpropsとして渡す値を指定する
import React, { useState, createContext } from'react' // 1
import DisplayModefrom'../../../shared/variable/DisplayMode'
export const DisplayModeContext = createContext() // 2
<DisplayModeContext.Provider value={{ isEditMode:isEditMode }}> // 3
<DisplayMode/>
</DisplayModeContext.Provider>
...割愛
受け取る側
- useContextをimportする
- わたす側のコンポーネントでexportした項目をimportする
- useContextで2を引数にして宣言することで使用できる
import React, { useContext } from 'react' // 1
import { DisplayModeContext } from '../../atomic/Pages/Stock/Stock' // 2
const DisplayMode = () => {
const displayModeState = useContext(DisplayModeContext) // 3
return (
<>
{displayModeState.isEditMode ? (
<div
React Fragment
- divタグを不要に生成するよりも、仮想DOMに作成されるノードが1つ減るため、パフォーマンス的にもGood
- レンダー内で条件式や、変数、関数を定義しないように。可視性が低下する
render() {
return (
<React.Fragment>
<ChildA />
<ChildB />
<ChildC />
</React.Fragment>
);
}
propsで動的にstyleを切り替える
StockEditForm.jsx(親)
import BasicButton from '../../Atoms/Button/BasicButton'
const StockEditForm = () => {
return (
<BasicButton bg="BLUE" buttonName={'確定'} />
<BasicButton bg="GREEN" buttonName={'編集'} />
)
}
BasicButton.jsx(子)
import React, { useCallback, useState, useEffect } from 'react'
import styled from 'styled-components'
const bgList = {
BLUE: '#83bfff',
GREEN: '#38B2AC'
...more
}
const Button = styled.button`
font-size: 1rem;
padding: 5px 10px;
border-radius: 5px;
cursor: pointer;
color: white;
// ↑ 共通のスタイル
// ↓ propsによって動的に切り替えるスタイル
// オブジェクトリテラルで複数条件に対応。条件の追加は、オブジェクトに追加するだけでOKなので容易
background: ${(props) => bgList[props.bg]};
`
const BasicButton = (props) => {
return (
// ここでstyled componentにpropsとして渡る
<Button bg={props.bg} className={props.className} onClick={props.onClick}>
{props.buttonName}
</Button>
)
}
export default BasicButton
コンポーネントのエラーハンドリング
- Reactでエラーが発生した場合は、何も対処していないと画面が真っ白になってしまう
- Error Boundaryは、子コンポーネントで発生したJavaScriptのエラーをキャッチ・記録しフォールバックのUIを表示するコンポーネント(try catchのようなもの)
- Reactのライフサイクルフック componentDidCatchを使用する
- ErrorBoundaryは次のエラーをキャッチできないので注意
・イベントハンドラ
・非同期コード(例:setTimeoutなどのコールバック)
・サーバサイドレンダリング
・(子コンポーネントではなく)error boundary 自身がスローしたエラー
ErrorBoundaryコンポーネント
今のところ、functionalコンポーネントで実現できない様子(専用のライブラリはあるよう)
import React, { useCallback, useState, useEffect } from 'react'
class ErrorBoundary extends React.Component {
constructor(props) {
super(props)
this.state = { hasError: false }
}
componentDidCatch(error, errorInfo) {
this.setState({ hasError: true })
}
render() {
if (this.state.hasError) {
return (
<>
<h1>申し訳ございません。お探しのページが見つかりませんでした。</h1>
<img src={'404.png'} alt="" />
<a href="/stocks">在庫一覧に戻る</a>
</>
)
}
return this.props.children
}
}
export default ErrorBoundary
エラーをキャッチしたいコンポーネントをラップ
<ErrorBoundary>
<StockTable {...{ headerList, stocks, isEditMode, toggleMode }} />
</ErrorBoundary>
React DevToolsでデバッグ
React DevToolsは、ChromeとFirefoxで使えるブラウザ拡張機能で、ブラウザからコンポーネントやpropsの値などを確認することが可能です
まとめ
いかがでしたでしょうか。本記事では、全5部構成でReactの基礎知識や知っておくと便利なTIPSについて紹介しており、そのPart4の内容になります。対象者としてはReactの初学者~中級者を対象としており、Reactの基本的な書き方は知っているが、細かい処理や仕組みについては理解できていないという方には役に立つのではないかと思います