Reactキャッチアップ
default export
ではなくnamed export
を使うメリット・デメリット
Qiita開発チームがReactの開発で default export を使わなくなった理由
default export にしてしまうと、import側で自由に名前をつけることができてしまい、コンポーネント名が統一されなくなってしまいます。
named exportの場合、importする側ではexport側で定義された名前をそのまま使うことになります。
コンポーネント名を変更したらエラーが起きるのでコンポーネント名の変更忘れに気づくことができる。
ただし、React.lazy
はdefault exportでないと使えないらしいので注意。
ローディング画面に使えそうなUI
React Loader Spinner
Notionにまとめたやつ
Create React Appにおける差 - npm / npx / yarn -
結論
- npx、npmでCRAするとreact-scriptsの脆弱性を指摘されるが無視して良い。
- 上記脆弱性が気になる場合は、package.jsonを書き換えてから
npm audit --production
をすると良い(詳細は記事内にあります) - yarnで作成すると脆弱性のエラーは出ない。
- yarnで作成すると出現するファイルのコミット管理は
.yarn ⇨ 管理しない
.pnp.* ⇨ キャッシュも管理するかどうかによる
で分ける。 - npmならnpm、yarnならyarnで管理したほうが良い。
ESLintエラー
Compiled with problems:
ERROR
[eslint] Failed to load config "react-app" to extend from.
Referenced from: パス
Windows特有のエラー。大文字小文字の判別をしないため、パスが一致せず起きるらしい。
あるいはReactのESLintが競合している。
私の場合は後者だったため、package.jsonから下記を削除
"eslintConfig": {
"extends": [
"react-app",
"react-app/jest"
]
}
npmでCRAやったときは出なかったのでyarnで出たエラーっぽい
参考
Failed to load config "react" to extend from
Reactでローカル環境で実行するとエラーが出る
Issue#4186
【 React 】npm start 実行後の画面に「 [eslint] Plugin "react" was conflicted between "package.json » eslint-config-react-app 」というエラーメッセージが表示される。
[dedupe] Plugin "react" was conflicted を解決する
Create-react-app - ERROR in Plugin "react" was conflicted between ".eslintrc.json" and "BaseConfig"
yarn dedupe
Plugin "react" was conflicted between package.json » eslint-config-react-app
内容ピックアップ
- propsなどの分割代入強制
- 関数コンポーネントの定義方法を統一。関数宣言、関数式、アロー関数から選択可
- useStateを[value,setValue]に統一
- React Fragmentの書き方統一
- 不要な中括弧削除
- 不要なReact Fragment(
<></>
)削除 - 子要素がない場合は自己終了タグ利用
- コンポーネント名をパスカルケース
- booleanをisやhas開始で統一
- イベントハンドラの命名統一
ReactにもRailsでいうRSpecみたいなテストコードがかけるらしい
テスト概要
できること
- コンポーネントツリーのレンダー
- アプリケーション全体の動作
推奨ツール
テストツールは深堀りすると長くなりそうだから、やるとしたら別のスクラップを作ろう
言語ローカライズパッケージi18n。Railsで知っていたがReactにもあった
react-i18next
使い方
※ドキュメントを起こしただけでまだ実際に試していない
インストール
npm install react-i18next i18next --save
i18n.js
ファイルをindex.js
と同じ階層に作成し、色々設定をする。
import i18n from "i18next";
import { initReactI18next } from "react-i18next";
const resources = {
en: {
translation: {
"Welcome to React": "Welcome to React and react-i18next"
}
},
jp: {
translation: {
"Welcome to React": "ようこそReactとreact-i18nextへ"
}
}
};
i18n
.use(initReactI18next)
.init({
resources,
lng: "ja",
interpolation: {
escapeValue: false
}
});
export default i18n;
index.js
で読み込み
import React, { Component } from "react";
import { createRoot } from 'react-dom/client';
import './i18n';
import App from './App';
const root = createRoot(document.getElementById('root'));
root.render(
<App />
);
呼び出しはフックを使う
import { useTranslation } from 'react-i18next';
const MyComponent = () => {
const { t, i18n } = useTranslation();
return <h1>{t('Welcome to React')}</h1>
}
useState
は非同期で変更される。
変更を検知すると再レンダリングが走る。
useRef
は同期で変更される
再レンダリングの影響を受けず、値が変更されても再レンダリングされない。
値を更新した直後に参照すると、新しい値が使えるが関数スコープが変わると更新前の値が参照される。
つまりコンポーネントを超えるとアウト。
再レンダリングの必要があるもの ⇨ useState
再レンダリングの必要がないもの&再レンダリング時に中身が変わらないもの ⇨ useRef
って使い分けにするといいのかな
useEffectは再レンダリングのたびに実行される。
初回のみ実行で再レンダリングのときに影響を受けたくないときは、useCallbackとuseMemoを使うのも手。
useMemoは関数コンポーネント内で使われるフック、memoは関数コンポーネント自体に適応するもの、の違い。
useEffectは
- マウント時に1度呼び出される
- 依存関係のある(第2引数に入れた変数)の変更を検知して呼び出される
空配列であればマウントのとき1回のみの実行になる。
マウントはDOM画鋲がされるタイミング
アンマウントはDOMが廃棄されるタイミング
React state とライフサイクル