20220116のReactに関する記事は12件です。

【React】分割代入でPropsの値を受け取る

TL;DR interface Props { firstName: string lastName: string } const sampleComponent: FC<Props> = ({ firstName, lastName}) => { // firstNameの記述だけで値を受け取れる } このように記述すれば、Propsの中のプロパティをそのまま使用することができる 分割代入ってなに? 分割代入(Destructuring assignment) 配列やオブジェクトからプロパティを取り出して、別個の変数に代入することを可能にする構文 従来のPropsの受け取り方 これまでPropの値を受け取る時は下記のようにしていました。 interface Props { firstName: string lastName: string } const sampleComponent: FC<Props> = props => { // props.firstNameでPropの値を受け取れる } これのショートハンドがTL;DRで記載した内容です 参考
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

ReactとNode.js、AWSで社内システムを構築するまで 1/2

こんばんは。natariです。 社内システムの構築プロジェクトが終わったので、日記風にどんなことをやったかを書いていきます。 まず、プロジェクトの概要ですが、社内でExcelで管理している出社状況データ(今日は○○さんはテレワークだよーとか、〇日はお休みだよーとか、部の出社率とかを管理するもの)のweb化でした。 上長からこんな技術使ってとか、こんな風に作ってという指定はありませんでした。 なのでまずは社内の集会などを利用して、どんなシステムを作ったらいいかという皆さんの要望を聞き出すヒアリングから開始しました。 大体20人くらいの方から意見を頂き、すべての意見を反映させることは出来ないので、要望の数が多いものをピックアップして、あとはExcelで管理していたデータをそのままweb上で再現することとしました。 ここで僕にとって幸福だったのは、使用技術の指定がなかったことです。ちょうどプライベートでReactやTypeScript、Node.js、AWSあたりを勉強していたので、SPAでWebアプリを作ってみようと思い、この4つの技術を使うこととしました。 SPAについて簡単に説明すると、従来のよくあるフレームワークでのWebアプリの作り方とは異なり、クライアントとサーバーサイドを独立させて、データのみをやり取りする手法です。 ちなみに現在はGolangで別途APIサーバを作ってこんな感じで機能追加する予定です。 (プライベートで) まず、React(クライアント側)ですが、stateとpropsを使っていきます(当たり前)。 社内には部署が4つあります。そのため部署1~4のstateが必要です。 そしてカレンダーは月ごとに管理しているので、年(2022とか)と月(1~12)のstateも必要です。 次にログイン機能です。ログイン機能の作成についてはこちらの記事で詳しく説明しています。 https://qiita.com/natarisan/items/b43219f03566da8d0a66 ログインしているクライアント情報を保持するstateも必要です。 これらのstateをprops(場合によってはuseContextとか)を用いてうまいことコンポーネント間で共有します。 そして、各stateが変わったとき、そのstate応じたデータをfetchメソッドやaxiosメソッドでNodeサーバと通信して取ってきます。こんな感じで、fetchメソッドの中に現在のstateを当てはめる形でサーバにリクエストを送りました。 データベースもstateに対応するよう作成し、stateに対応するデータを返すようにしました。 同じくサーバ側で対応するデータの出社率計算機能も作成し、ひとまずアプリは完成です。 React-routerなども用いてやっとSPAっぽくなったなあという印象でした。 続いての記事は、作成したアプリをAWSにデプロイするまでを書いていきます。 今回は以上です。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

React チュートリアル パート8 (Crudシステム)

目標 アプリケーションに追加と削除の機能を作りましょう この機能をマスターすれば、アプリケーションでできることが増えますね App.jsを作成 前回作成した、List.jsは削除しています 【3行目】 まず、ターミナルで"npm install nanoid"をインストールします。 【11行目】 コンポーネント何で配列を作成しました。 【25行目】ここから追加機能になります。 【26行目】"e.preventDefault();は、ボタンをクリックされない限りこの機能が動かないようにしています。 【36行目】ここで、nanoid()が登場しています。自動性IDを生成します。 【47行目】ここからが削除機能になります。filter()を使って、渡されたid以外の要素をフィルターにかけています。 ブラウザで確認 次回 今回のアプリケーションは、ページをリロードするとリセットさせるので次回は、JSON-Serverを使って外部からデータを取得したり削除したりする機能を追加したいと思います! 参考
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

redux のソースコード を読んでみる

試しに redux を読んでみたので、そのまとめ。 この記事では、react-redux を除いた redux、つまり createStore を使った getState・dispatch 操作を、実際の redux のコードを読んで理解してみます。 対象読者 redux の使い方を知っている人 redux まとめ まずは、簡単な概要を説明します。 redux は 状態管理 のライブラリ。 React の State状態管理 のバケツリレーを改善するために、大きな State を作っておき そこにデータアクセス(react-redux)することで状態管理をする。ここでは「大きな State を作る」部分である redux だけを解説します(暇があれば、後半の「データアクセス」部分をしている react-redux も読んでみます)。 React で呼び出している redux は、reducer をまとめる combineReducers と createStore です(細かい redux の使い方は省きます)。 index.js import {createStore} from "redux" import {reducers} from "reducers" import {someAction} from "actions" ・・・省略 store = createStore(reducers) store.dispatch(someAction) console.log(store.getState()) reducers/index.js import {combineReducers} from "redux" import {hoge} from "./hoge" export const reducers = combineReducers({hoge: hoge}) reducers/hoge.js export const hoge = (action, state) => { switch(action.type) { case: "HOGE": /* do some stuffs */ return new_state default: return state } } combineReducers では、まずは combineReducers から読んでみましょう。 ソースコードは、 redux:src/combineReducers.ts から。 src/combineReducers.ts function getUnexpectedStateShapeWarningMessage(...){ /* stateの型を確認する関数 */ } function assertReducerShape(...){ /* reducerの型を確認する関数 */ } export default function combineReducers(reducers: ReducersMapObject) { const reducerKeys = Object.keys(reducers) const finalReducers: ReducersMapObject = {} for (let i = 0; i < reducerKeys.length; i++) { /* 関数なら、finalReducers に reducer を登録 */ const key = reducerKeys[i] if (typeof reducers[key] === 'function') { finalReducers[key] = reducers[key] } } const finalReducerKeys = Object.keys(finalReducers)  ・・・reducer の型チェック return function combination(state, action){ let hasChanged = false const nextState: StateFromReducersMapObject<typeof reducers> = {} for (let i = 0; i < finalReducerKeys.length; i++) { /* reducer を 実行 */ /* 上の例で言えば、hoge の switch文 */ const key = finalReducerKeys[i] const reducer = finalReducers[key] const previousStateForKey = state[key] const nextStateForKey = reducer(previousStateForKey, action) /* state が 更新された */ nextState[key] = nextStateForKey /* 更新されたか確認 hasChanged */ } return hasChanged ? nextState : state } } ここでは、上記の reducers/hoge.js export const hoge = (action, state) => { switch(action.type) { case: "HOGE": /* do some stuffs */ return new_state default: return state } } などの reducer を受け取って、まずは function の reducer のみのオブジェクト finalReducers を作っています。 そして、後で出てきますが 実際に 引数(action, state) で呼び出された場合(クロージャーになっています) に、finalReducers の1つ1つの reducer に 引数(action, state) を渡し、reducer で state を更新します(上の hoge.js のような形で)。 createStore 次に、createStore を読んでみましょう。 ソースコードは、src/createStore.ts から。 createStore では、主に getState・subscribe・dispatch・replaceReducer の4つの関数があります。 createStore.ts export default function createStore(reducer, preloadedState? , enhancer?) { ・・・省略 let currentReducer = reducer let currentState = preloadedState let currentListeners: (() => void)[] | null = [] let nextListeners = currentListeners let isDispatching = false ・・・省略 function getState(){ ・・・省略 } function subscribe(listener){ ・・・省略 return function unsubscribe(){ ・・・省略 } } function dispatch(action){ ・・・省略 } function replaceReducer(nextRuducer){ } } ここで出てくる getState() と dispatch(action) は 使ったことがあるかもしれませんね。react-redux がないと、この 2つの関数を使って「State の取得」と「State の更新」をしていましたね。 他の subscribe と replaceReducer は、それぞれ「変更があるたびに呼び出す関数の登録」と「reducer の変更」ができます。 今回は、この中の getState と dispatch を見てみましょう。 まずは、getState() createStore.ts function getState(){ ・・・省略 return currentState } これは簡単ですね。単に currentState を返しているだけです。 では次に dispatch を見てみましょう。 createStore.ts let currentReducer = reducer ・・・省略 function dispatch(action){ ・・・型チェック try { isDispatching = true currentState = currentReducer(currentState, action) } finally { isDispatching = false } ・・・subscribe() で登録した listener の呼び出し return action } dispatch では、combineReducers した currentReducer でクロージャーされた関数を呼び出しています。 なので前の currentReducer で出てきた src/combineReducers.ts return function combination(state, action){ ・・・省略 for (let i = 0; i < finalReducerKeys.length; i++) { ・・・省略 const nextStateForKey = reducer(previousStateForKey, action) ・・・省略 } return hasChanged ? nextState : state } の関数がそれに当たり、state の更新を行なっています。 他にも applyMiddleware などありますが、大体、内容は以上になります。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

1週間でReact(Next)をキャッチアップした際の学習手順【ほぼリンク集】

初めに 今回はタイトルの通り、僕が1週間程度で最低限Reactを使いこなしポートフォリオを作成できるようになるまでに行ったことをまとめようと思います! Reactといってもクラスコンポーネントと関数コンポーネント(Hooks)がありますが、今回はHooksについてのみ触れます。 最終的なゴールは成果物を作ることで、Next.jsを利用します。 余談になりますが、なぜ1週間という短期間でキャッチアップする必要があったかと言いますと 転職活動の際に第一志望の企業様との最終面接を控えていたのですが体調不良で大幅に延期していただくことになってしまったため、誠意として急いで志望先企業の技術を使いポートフォリオを作成してお出ししたという感じです...笑 ちなみに僕のスペックは以下の通りです↓ 最終学歴は美容専門卒 未経験からエンジニアに転職、3年目(歴2年3ヶ月程度) 業務で用いている技術は主にVue.js(Nuxt.js),TypeScript 対象読者 フロントエンドの基本的な知識はあるがReactは未経験という方に一番適している記事かと思います。 自分が学習する際にClassベースの書き方とHooksの情報が入り乱れておりどこから手をつければ良いか迷ったため記事を書くに至ったのですが、本記事はHooksを速習したい方のみに向けています。 本題 基本的に自分は動画学習が好きなので、Youtubeのリンクが多めです? 1. Reactの基礎 新・日本一わかりやすいReact入門【基礎編】Reactの基礎知識 #1 〜 #9 2. Next.jsの基礎 【日本一わかりやすいNext.js入門】#1 〜 #8 Reactに続きこちらもトラハックさんという方のYoutube講座です? Next.jsの公式チュートリアルを元に作られているので英語が得意な方は公式チュートリアルでも良いかもしれません。 全部で10講座ありますが、Nextについてだけ学べば良い方であれば#8までご覧いただけば十分かと思います。 Vercelへのデプロイまで含んでいるので、短期間で成果物を作りたい自分にとても合っていました。 3. 成果物用に環境構築 Next.jsで作る技術ブログ [Part1 - セットアップ] こちらのYoutube講座はpart4までありますが今回はpart1のみで大丈夫です。 動画からは主にLinter周りのsetupを参考にしました。 該当するChapters? 3:45 ESLint 9:17 Prettier ⚠️ TSを用いたい場合の注意点です! 動画には登場しませんが、下記の通りにすればTSの設定を自動で行ってくれます。(収録された時期にはオプションが無かったのかもですね? ) また動画の通りの設定にするとTSの型チェックが甘めになるので、厳格にしたい方はtsconfig.jsonにてstrict: true の指定をお忘れなく。 npx create-next-app@latest --ts # or yarn create next-app --typescript 余談ですが、dockerコンテナを立てたりmysqlを用意したりしたい場合はこちらがとても参考になりました? Docker+Express+MySQLの環境をつくる 4. 成果物作成に取り掛かろう! ここからは上記の1.2.で学んだことを用いてお好きなwebアプリを作成してください!(丸投げ) 自分の場合は特にCSSの技術選定に迷いましたが、Vueでの実装でRSCSSとITCSSを組み合わせての書き方に慣れていたのでCSS Modulesにしました。 (ですが後で調べたら将来的に非推奨になるっぽい?です?  参考:https://github.com/webpack-contrib/css-loader/issues/1050#:~:text=In%20the%20near%20future%20we%20want%20to%20deprecate%20CSS%20modules%2C ) この辺りは自分も特に詳しくないので有識者の方にコメントいただけるととても嬉しいです...! 最後に 僕は公式ドキュメントみっちりとを読み込む精神力を持ち合わせていないタイプで、新しいことを学ぶ際にはとりあえず概要だけサクッと知りたい...と言った心理になります。 そのため、いつもYoutubeやUdemy、またQiita,Zennなどで速習できるような教材をいくつか組み合わせて学ぶのですが、もしかしたら同じ価値観の方の役に立てるのでは??と考え執筆した次第です。 とはいえ、僕自身もまだまだReact初心者なので間違ったことを言っていた場合はぜひコメントください?‍♂️ またQiitaの記事も書き慣れていないので何か問題行為があればこちらもコメントいただけると幸いです、すぐに修正いたします。 最後までお読みいただきありがとうございました!!
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

React×TypeScript 基本の型定義

はじめに 業務でフロント側はReact(Next.js), TypeScriptを使っているのですが、配属当初の私はReactにもTypeScriptにも触れたことが無く、何が分からないのか分からない状態でした。 TypeScriptの基礎を学んでもReact特有の型定義があり戸惑いましたが、ようやく理解して書けるようになって来たな…ということで、辞書代わりにまとめておきます。 (誤りのご指摘・アドバイスがあればぜひお願いします!) 基礎編 まずは基本の型定義を一通り挙げます。 関数コンポーネント 関数コンポーネントでは、普通の関数と同じように引数(props)に型付けします。 戻り値はJSX要素を返せば型推論されるので、明らかな場合は型付けしなくてOKです。 ※以下の例では、propsは分割代入の書き方で受け取るものとします。 引数(props)なしの場合 propsを受け取らない場合は、JavaScriptで記述するときと変わりません。 // ノーマルの関数コンポーネント(引数なしの場合) const App = () => <div>なまえ</div> ひとつのpropsを受け取る // 引数に型付けする const App = ({ name }: { name: string }) => <div>{name}</div> // 型エイリアスを使っても良い type Props = { name: string } const App = ({ name }: Props) => <div>{name}</div> 型注釈を直接つけても、型エイリアスを使ってもOKです。 プロジェクト内で合わせておけば良いかと思います。 複数のpropsを受け取る propsを複数受け取る場合は、型注釈を直接つけるよりも型エイリアスを付けた方が分かりやすいでしょう。 // 引数が複数なら、型エイリアスを使う方が見やすい type Props = { name: srting onClick: () => void children: ReactNode } propsの型いろいろ 以下のように色々な型の値をpropsとして受け取ることができます。 ここはほとんどTypeScriptの基本通りです。 // propsとして受け取る値の型定義色々 type Props = { str: string // 文字列 num: number // 数値 bool: boolean // 真偽値 strArr: string[] // 配列 obj: { // オブジェクト str: string } objArr: { // オブジェクトの配列 str: string num: number }[] func: () => void // 関数 } children childrenはコンポーネントのタグで囲った子要素をpropsとして受け取るときに使います。 よく使うのはReactNodeで、これはコンポーネントタグで囲ったJSX要素をまるっと受け取る場合に使います。 // 共通レイアウトのコンポーネント const MainLayout = ({ children }: { children: React.ReactNode }) => { return ( <> <Header /> <div> {children} </div> <Footer /> </> ) } // 呼び出し側 const MenuPage = () => { return ( <MainLayout> // この中にページの内容を書く </MainLayout> ) } もし特定の文字列や数値しか受け取らないというような場合は、ReactNodeではなく特定の型に制限することもできます。 // Buttonコンポーネント const Button = ({ children }: { children: string }) => { return ( <button>{children}</button> ) } // 呼び出し側 const App = () => { return ( <>    // フォームの記述があるとする <Button>送信</Button> <Button>戻る</Button> </> ) } ちなみにReactNodeは以下の通りのUnion型で定義されています。 type ReactNode = ReactChild | ReactFragment | ReactPortal | boolean | null | undefined; propsのデフォルト値を指定する コンポーネントの利用箇所ごとにpropsに渡す値を指定してもよいのですが、デフォルト値を指定することもできます。 よく指定される値がある時や、値が無かった場合の値を決めておきたい場合に有効です。 const Name = ({ name = "ゲスト" }: { name?: string }) => <div>{name}さん</div> オプショナルなprops(undefined許容) ? を付けることでオプショナルな型定義が出来ます。 以下のように書いた場合、name・emailの型はstring | undefinedとなります。 type Props = { name?: string email?: string } この場合はundefinedの可能性を考慮してpropsの初期値を設定するか、値の有無による条件分岐を行います。 // nameは初期値を設定、emailはpropsの値が渡された場合のみ表示する const Button = ({ name = 'ゲスト', email }: Props) => { return ( <div> <p>{name}さん</p> {email && ( <p>email:{email}</p> )} </div> ) } 戻り値の型付け JSX要素を返せば型を指定していなくても推論してくれますが、明示しておけば正しい値が返されなかった場合エラーを表示してくれます。 const App = ({ name }: { name: string }): JSX.Element => <div>{name}</div>; React.FC / VFC React.FC / VFC については、TypeSctriptを導入するのであれば不要と考えられるのでここでは取り上げません。(今の私の業務では使っていないのですが、もしなにか誤りやアドバイスがあれば是非ご教授ください…!) 参考記事:【検証】React.FC と React.VFC はべつに使わなくていい説 useState 状態変数の型 型推論に任せる useStateフックでは初期値を与えれば状態変数の型を推論してくれます。 なので極力初期値を与えて、推論させるようにします。 // プリミティブ値 const [name, setName] = useState("") // string型 const [count, setCount] = useState(0) // number型 const [isChecked, setIsCheked] = useState(false) // boolean型 // 配列 const [colors, setColors] = useState(["red", "blue"]) // string型の配列 const [numbers, setNumbers] = useState([1, 2, 3]) // number型の配列 ジェネリック型で指定する 基本の指定方法 useStateの状態変数に対して明示的に型を指定する場合は、ジェネリック型 <T> を使います。 // useStateのジェネリック型<T>に明示的に型を指定する const [name, setName] = useState<string>("") // string型 const [count, setCount] = useState<number>(0) // number型 const [isChecked, setIsChecked] = useState<boolean>(false) // boolean型 別途定義した型をジェネリック型で指定する 別途定義したオブジェクトを初期値にしたり、別途定義した型をジェネリック型で指定することもできます。 (型や初期値を複数のコンポーネントで使い回す場合や情報量が多くなる場合は、別ファイルに切り出しても良いかと思います。) const initialUser = { number: 1, name: '名前', email: 'test@mail.com' } type User = { number: number name: string email: string } const [user, setUser] = useState<User>(initialUser) ユニオン型でnullを含める 値がnullの可能性があるときや、型は定めておきたいが初期値は後から決まるといった場合は、ユニオン型でnullを含めます。 // nullを含む場合はユニオン型を用いる const [count, setCount] = useState<number | null>(null) // number型もしくはnull型 型アサーションを使う 状態変数の初期値が決まらないけれどnullは許可しないという場合には、型アサーションを使うことができます。 まず、以下の書き方ではエラーが出ます。 type User = { number: number name: string email: string } const [user, setUser] = useState<User>({}) user[name] = 'ゲスト' // userは「空のオブジェクト型」とTypeScriptは認識するのでコンパイルエラーになる そこで有効なのが型アサーションです。 type User = { number: number name: string email: string } const [user, setUser] = useState<User>({} as User) // 型アサーションを使えばコンパイルエラーが出ない ただし型アサーションはTypeScriptに型を偽っているだけなので、もし必要なプロパティを忘れていてもコンパイラエラーが指摘してくれないので、なるべく初期値を設定して型アサーションを使わずに済む実装にした方がベターです。 もし全てのプロパティが任意ならば、初期値に空オブジェクトを与えても問題ないので型アサーションは必要ありません。 type User = { name?: string email?: string age?: number } const [user, setUser] = useState<User>({}) // userはUser型のうち任意のプロパティを持つ(空オブジェクトの可能性もある) useEffect useEffectの戻り値は undefined もしくはクリーンアップ関数と決められており、戻り値を処理しないため型は必要ありません。 ただし関数や値を返してしまうとエラーになるので、アロー関数の書き方に注意が必要です。 以下の書き方では、アロー関数式=>の本体に波括弧{}なしに1行で書いた文が戻り値になってしまいます。 useEffect(() => setTimeout(() => // 処理 , 1000); , []); 以下のように、本体を {} で囲むようにしてください。 useEffect(() => { setTimeout(() => { // 処理 }, 1000); }, []); イベントオブジェクトの型 onClickやonChangeといったイベントハンドラで扱うイベントにも型があります。 イベントオブジェクトの型を知りたいときは、VSCodeがヒントをくれます。 例えばonClickなら、以下の状態でonClickの上にマウスをホバーさせると型情報を表示してくれます。 <button onClick={}></button> 以下のように要素のイベント属性に直接イベントハンドラを書く場合は、引数のイベントの型は推論されるので注釈が要りません。 <button onClick={(event) => //処理 }></button> イベントハンドラの関数を別途定義する場合は、通常の関数と同様に型付けが必要になります。 onClickイベント 引数のイベントと戻り値に型付けをします。(戻り値は推論させてもOKです) // Buttonクリックの場合 const onClickButton = ( event: React.MouseEvent<HTMLButtonElement, MouseEvent> ):void => { // 処理 } onChangeイベント // Inputの場合 const onChangeInput = ( event: React.ChangeEvent<HTMLInputElement>):void => { // 処理 } 複数種類の要素にイベントを適用する 上記の例を見ると、ジェネリック型の部分に HTMLButtonElement HTMLInputElement とあるように特定のHTML要素のための型であることがわかります。 もしDivタグ・Buttonタグ・Inputタグなどに同じイベントハンドラ関数を指定したい場合、通常は HTMLButtonElement | HTMLInputElement | 続く... と使いたい要素分の型を記述する必要があります。 そんな時は、色んなHTML要素に共通して使える HTMLElement 型を使うこともできます。 type Props = { onClick: (event: React.MouseEvent<HTMLElement, MouseEvent>) => void } 以下の記事に詳しくまとめられており、非常に分かりやすかったです。 個人的には、精度を高めるためには面倒でも使う要素分だけ指定する方が良いのかな…?とも思いますが、 HTMLButtonElementもHTMLInputElement もHTMLElement 型を継承しているんだと知り、勉強になりました。 any型で諦めない React.EventCallback - Qiita 【番外編】Axios Axiosを使って非同期通信を行う際に返されるレスポンスやエラーにも型があります。 import { AxiosError, AxiosResponse } from 'axios' axios .get('/url') .then((response: AxiosResponse) => { // 成功時の処理 }) .catch((error: AxiosError) => { // エラー時の処理 }) おわりに 正直はじめは、何か書くたびにエラーが出るしコード量が増えて余計にわけわからんと思いました。 でも慣れてくると、型が明示してあると処理の流れを追わなくてもどういう値が入って来るのかパッと見でも分かりやすいし、エディタの補完が効くのは便利で間違いがあれば気付けてTypeScript良いなと思うようになりました。 今後もより実用的でスマートな型の活用法を学んでいきたいと思います。 参考記事
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

ReactでMUI v5でスタイリングエンジンに`styled-components`を使用するための設定

TL;DR 1. 以下のコマンドを実行してMUIのコアライブラリである@mui/material、styled-componentsとラッパーライブラリである@mui/styled-engine-scをインストールします。 $ yarn add @mui/material @mui/styled-engine-sc styled-components 2. package.jsonで@mui/styled-engineが参照するスタイルエンジンの指定を@mui/styled-engine-scに変更します。 { "dependencies": { - "@mui/styled-engine": "latest" + "@mui/styled-engine": "npm:@mui/styled-engine-sc@latest" }, + "resolutions": { + "@mui/styled-engine": "npm:@mui/styled-engine-sc@latest" + }, } 詳細 1. @mui/material、styled-componentsとラッパーライブラリである@mui/styled-engine-scをインストールします。 yarn add @mui/material @mui/styled-engine-sc styled-components ライブラリをインストールしただけの状態でビルドすると以下のエラーが発生してしまいます。 ERROR in ./node_modules/@mui/styled-engine/GlobalStyles/GlobalStyles.js 3:0-40 Module not found: Error: Can't resolve '@emotion/react' in '/app/node_modules/@mui/styled-engine/GlobalStyles' ERROR in ./node_modules/@mui/styled-engine/StyledEngineProvider/StyledEngineProvider.js 3:0-47 Module not found: Error: Can't resolve '@emotion/react' in '/app/node_modules/@mui/styled-engine/ ERROR in ./node_modules/@mui/styled-engine/index.js 6:0-39 Module not found: Error: Can't resolve '@emotion/styled' in '/app/node_modules/@mui/styled-engine' ERROR in ./node_modules/@mui/styled-engine/index.js 26:0-62 Module not found: Error: Can't resolve '@emotion/react' in '/app/node_modules/@mui/styled-engine' 2. スタイリングエンジン変更の設定 リファレンスにも書いてある通りなのですがstyled-componentsをスタイリングエンジンに使用する場合はもう一手間加える必要があります。 MUIのコアライブラリである@mui/materialは内部で@mui/styled-engineに依存しているのですが、@mui/styled-engineのデフォルトの設定ではスタイリングエンジンにemotionが指定されているので、スタイルエンジンの指定を@mui/styled-engine-scに変更する様に設定します。 @mui/styled-engine-scは公式リファレンスのInstallationセクションに書いてあるようにyarn addコマンドでインストールするのではなくpackage.jsonを手書きで以下の様に書き換えてyarn installする必要があります。 { "dependencies": { - "@mui/styled-engine": "latest" + "@mui/styled-engine": "npm:@mui/styled-engine-sc@latest" }, + "resolutions": { + "@mui/styled-engine": "npm:@mui/styled-engine-sc@latest" + }, } その他 ❗ Warning: Using styled-components as an engine at this moment is not working when used in a SSR projects. The reason is that the babel-plugin-styled-components is not picking up correctly the usages of the styled() utility inside the @mui packages. For more details, take a look at this issue. We strongly recommend using emotion for SSR projects. CSSの名前を動的に決定する仕組みの関係からSSRで使用する場合に正しく動作しないとの事で、SSRで使用したい場合はemotionをスタイリングエンジンに使用することを推奨しています。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

状態管理どうしてますか?

昨年7月の話になってしまいますが、スタートアップReact LTで「状態管理どうしてますか?」と題して、発表しました。 tl;dr justInCaseTechnologiesウェブフロントエンド、2021年7月時点での大まかな方針: 小規模のプロダクトには Recoil / Jotai を使っていく 中規模以上のプロジェクトでは Redux Toolkit を使っていく スライド 状態管理どうしてますか? from Takuya Otani サンプルコード github にサンプルコードを挙げています。 context-sample jotai-sample mobx-sample recoil-sample redux-sample zustand-sample にそれぞれのライブラリを使ったサンプルプロジェクトが納められています。 dist ディレクトリにある index.html だけ共有していますが、基本各サンプルは独立させているので、それだけ取り出してボイラープレートのように使っていただくことも可能だと思います。 各ライブラリの感想 React Context 他のライブラリに依存せず、 React だけで完結するのは強みですが、どうしても Context を設定するための記述が必要になってしまい、状態管理という本来の目的から外れた部分の実装が目に付く印象です。 Redux Toolkit この発表した当初は justInCaseTechnologies では Redux Toolkit を採用したプロダクト・プロジェクトはありませんでした。 個人的には別の会社で以前 Redux を使ったことはありましたが、「おまじない」が多くそれがちょっと苦痛だったりしたのですが、今回この発表をきっかけに Redux Toolkit を使ってみたら、簡潔にわかりやすく記述できるようになっていてその印象が変わりました。 MobX justInCaseTechnologies では、他ライブラリの依存関係などもあって、当初の最新版 (v6) は利用していませんでしたが、発表では v6 でサンプルコードを組んでみました。 v4 までのデコレータを多用した実装とは異なり、すっきりとした記述での実装ができるように。一方で class を使った実装から離れていくという React のトレンドとはちょっと異なる部分もあるのでちょっとしたモヤモヤ感……。 Recoil 比較的新しい状態管理ライブラリ。 atom という単位で状態をとりまとめていくスタイル。後述する Jotai も同じようなアプローチを取っていています。 この管理の仕方、管理する状態が少なければそんなに問題にならないのですが、増えてくると追いかけるのが大変になってきます。ライブラリが軽量なのもあって取り回しは良い印象はあるのですが……。 Jotai Recoil 同様 atom 単位で状態を管理するというコンセプトのライブラリ。Recoil よりも記述量は減る傾向にあって、比較的すっきりとした実装にすることができるとは思います。 一方で Recoil でも触れたように管理する状態そのものが増えてきて、 atom 相互の関係性が複雑になってくるときつくなる印象は否めません。 発表できなかったこと 後述の通り、時間勘違いしていて、当日は全く触れることができなかったライブラリに Zustand (ツシュタント) があります。前掲のスライドでは「おまけ」として掲載。 カスタムフックの生成関数が用意されていて、作ったフックをコンポーネントで利用するという形になっています。全然知らなかったライブラリなんですが、使い勝手は良さそうで個人的には今後どこかで本格利用してみたいとは思いました。 発表を通して 発表準備のために、今回は実際にサンプルコードを組んでみましたが、React Contextを除いて、実装面においては正直このサンプルコードの規模感では、どのライブラリも大きく変わらない印象があるのは否めません(苦笑)。 一方で実際組んでみると、それぞれのライブラリの書き味は結構違うことも分かりました。Redux は Toolkit を通して利用すると以前実装に使っていたときよりも全然印象が異なったのは大きな収穫。以前と比べて React 周辺の技術スタックに対しての知識が増えたのも大きいとは思いますが。 Recoil / Jotai / Zustand あたりは重量感を感じることもなく、さっと導入できそうな印象があり、個人的には今後もちょっと注力していきたいと思っています。 発表当初は justInCaseTechnologies で利用していなかった Redux Toolkit 、その後の開発案件で利用するものが出てきています。最初から中規模以上を目指したものなら、手続きに関する記述が安定している Redux はチームで開発するプロジェクトには向いている印象を持っています。 発表の反省 ライトニングトーク、発表枠 15 分ということで準備していましたが、直前の打ち合わせで質疑応答含めて 15 分ということが発覚して、めちゃくちゃ焦りました。 結局発表だけでほぼ 15 分使い切ってしまったのは大反省(おそらく、オーバーしていたはず)。次回からはちゃんと時間確認します……。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【React】useContextの使い方

はじめに  本記事は、プログラミングの学習を始めて1ヶ月の初学者が、学習を進めていて疑問に思った点について調べた結果を備忘録も兼ねてまとめたものです。  そのため、記事の内容に誤りが含まれている可能性があります。ご容赦ください。  間違いを見つけた方は、お手数ですが、ご指摘いただけますと幸いです。 useContextの使い方 useContextとは Providerでラップしたコンポーネントのツリーのどこからでも、同一のContextObjectを参照できるようにするHookです。 propsのバケツリレーを避けることができます。 Contextを更新したときに再レンダーされるべきでないコンポーネントにも再レンダーが走る場合は、注意するべきでしょう。 useContextを使うタイミング コンポーネントの階層が深い場合や複数コンポーネントで同一stateを使用する場合に使用します。 useContextの使用例 App.jsx import React, {createContext, useState} from 'react' import Header from './component/Header' import Footer from './component/Footer' import Content from './component/Content' export const ChangeContext = React.createContext(); function App() { const [chageContext, setChangeContext] = useState(true); const value = { chageContext, setChangeContext }; return ( <div className="App"> <ChangeContext.Provider value = {value}> <Header /> <Content /> <Footer /> </ChangeContext.Provider> </div> ); } export default App; Content.jsx import React, {useContext} from 'react'; import {ChangeContext} from '../App'; import style from '../style/content.module.scss'; const Content = () => { const {chageContext, setChangeContext} = useContext(ChangeContext); return( <div className={style.content}> <h1> {chageContext ? 'content': 'コンテンツ'} </h1> </div> ) } export default Content;
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

React チュートリアル パート7 (コンポーネント&props)

目標 ReactJSの超重要知識 コンポーネントとpropsを見ていきましょう ディレクトリ構造 新しくcomponentsフォルダを作成し、そこにList.jsを作ります。 List.jsを作成 作業は2つだけです まずはじめに、List.jsを作成します!下記の様に記述してください!後ほど説明します 次に、App.jsを下記の様に変更してください。 【4行目】import 文を追加 【26行目】<List/>コンポーネントに変更 ➪①<List/>コンポーネントに、keyとdocumentを渡しています ➪②document={document}を解説すると、document(右)という値に、document(左)という名前を付けて<List/>コンポーネントに渡しています ➪③App.jsから渡された、documentをList.jsが受け取りそれをdocumentとして受けています(List.js 【3行目】)。これがpropsになります! ブラウザで確認 プラウザの表示には特に変わりありません! コンポーネントを作ることによって、役割を分担することができより読みやすいコードになったかと思います 次回 ReactJSで簡単な、CRUDシステムを構築してみます! そこで登場するのがfilter()メソッドです map()メソッドと同様とても大事なメソッドになるのでしっかり学んでいきましょう
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

React チュートリアル パート6 (style)

目標 文字に装飾を付けてみましょう App.jsに記述 divタグと、pタグにstyle属性を記述しています 【25行目】 style属性{{ }}にスタイルを記述していきます! ブラウザで確認 他にも、スタイルの記述方法はあります 一つ紹介すると、styled-componentsがあります!ぜひトライしてみてください 次回 次は、フックと同じぐらい大切なコンポーネントとpropsを学びます
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【JavaScript】ES5とES6において、親クラス継承の違い

ES5においての継承 <script> //親 function Phone(brand, price) { this.brand = brand; this.price = price; } Phone.prototype.call = function () { console.log(" give XXX a call") } //子 function smartPhone(brand, price, color, size) { Phone.call(this, brand, price); this.color = color; this.size = size; } smartPhone.prototype = new Phone; //親を呼び出す smartPhone.prototype.constructor = smartPhone; //子 メソッドの追加 smartPhone.prototype.photo = function () { console.log("take photo") } smartPhone.prototype.mail = function () { console.log("receive email") } let iphone = new smartPhone('iphone', 100, 'white', '6.7inch'); console.log(iphone); //smartPhone{brand: 'iphone', price: 100, color: 'black',size: '6.7inch'} </script> ES6での継承 <script> //親 class Phone { constructor(brand, price) { this.brand = brand; this.price = price; } call() { console.log(" give XXX a call") } } //子 *** extendsを使えば継承できる *** class smartPhone extends Phone { constructor(brand, price, color, size) { supre(brand, price); //イコール Phone.call(this,brand,price) this.color = color; this.size = size; } photo() { console.log("take photo") } mail() { console.log("receive email") } } let iphone = new smartPhone('iphone13', 200, 'pink', '6.1inch') console.log(iphone) //smartPhone{brand: 'iphone13', price: 200, color: 'pink',size: '6.1inch'} iphone.call()//" give XXX a call" iphone.photo() //"take photo" iphone.mail() //"receive email" </script> 違い ES6とES5と比べて、親クラスを継承するときのコードが明らかに簡潔ですね。 classとextendsを使えば、親クラスを継承できるので、 PHP、Javaなどの構造と似ているように思います。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む