20211013のReactに関する記事は8件です。

reactでwebpackの設定

webpackをインストール 以下のコマンドを実行 *webpack v4以降からはCLIもインストールする必要があるみたい。 npm i --save-dev webpack webpack-dev-server webpack-cli 次にwebpack.config.jsを作成 touch webpack.config.js 次に下記のコマンドを実行し、また.Babelrcを作成する。 //babelrcをインストール npm i --save-dev @babel/core @babel/preset-env @babel/preset-react babel-loader html-webpack-plugin //.Babelrcファイルを作成 touch .Babelrc 今回、buildしたときにcssが原因でエラーが出ていたのでstyle-loaderを追加した。 ↓その他のloader https://webpack.js.org/loaders/ npm i -D webpack webpack-cli style-loader css-loader webpack.config.jsに以下を貼り付け const path = require('path'); module.exports = { mode: 'development', entry: [ './src/index.js' ], output: { path: path.join(__dirname + '/dist'), filename: 'bundle.js' }, module: { rules: [ { test: /\.(js|jsx)$/, exclude: /node_modules/, use: [ { loader: 'babel-loader', options: { presets: [['@babel/preset-env', { modules: false }]] } } ] }, // buildした際にcssでエラーが発生していたためstyle-loaderを追加 { test: /\.css/, use: [ "style-loader", { loader: "css-loader", options: { url: false } } ] } ] }, resolve: { extensions: ['.js', '.jsx'] // use js, jsx file }, devServer: { open: true, historyApiFallback: true, contentBase: path.join(__dirname, '/dist'), watchContentBase: true, inline: true, hot: true, }, plugins: [ ], }; packeg.jsonのbuildコマンドを修正 "scripts": { "start": "start", "build": "webpack --mode production", "test": "test", } これでいけるはず
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Reactの環境構築

はじめに ここでは、Reactの開発環境構築をしていきたいと思います。 流れといたしましては、 1.Nodeのインストール 2.create-react-appのインストール 3.Hello Wordの表示 このような流れで行っていきたいと思います。 1.Node.jsのインストール まず、Node.jsがインストールされている確認します。 $ node -v v14.15.5     バージョンが表示されたら無事にインストールされている証拠です。 もし、バージョンが表示されていない場合は、下記からインストールしましょう。 https://nodejs.org/ja/ LTS版と最新版がありますが、LTS版が推奨されているので、LTS版をインストールしましょう。 そしてインストールした後、もう一度 $ node -v を実行してみてください。 バージョンが表示されたら、インストール成功です! 2.create-react-appのインストール 次は、create-react-appのインストールです。 create-react-appとは、簡単にいうと、アプリケーションの雛形を提供してくれるものとなっており、これを使用することによって、Babelやwebpackなどの複雑で様々なパッケージのインストールを行う必要がなく、簡単に必要なパッケージのみをインストールすることができます。 インストール方法はとても簡単です。 下記のコマンドを実行するのみです。 $ npx create-react-app my-app my-appの部分は、自分でつけたい名前に変更してください。 そして、 $ cd my-app $ npm start を実行します。 その後、ブラウザを立ち上げ、 http://localhost:3000/  にアクセスし、このような画面が表示されていたら、インストール成功です! 3.Hello Wordの表示 ここまで来たら、src配下にある、App.jsを開いてみましょう。 App.js import logo from './logo.svg'; import './App.css'; function App() { return ( <div className="App"> <header className="App-header"> <img src={logo} className="App-logo" alt="logo" /> <p> Edit <code>src/App.js</code> and save to reload. </p> <a className="App-link" href="https://reactjs.org" target="_blank" rel="noopener noreferrer" > Learn React </a> </header> </div> ); } export default App; このようなファイルが表示されていると思います。 こちらを以下のように書き換えましょう。 App.js import React from "react"; function App() { return ( <div className="App"> <h1>Hello World!</h1> </div> ); } export default App; そしたら、Hello Word!が表示されていると思います。 以上で、Reactの環境開発は終了です。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【React】TextFieldでEnterキーを押したときになぜかページが更新されてしまう件【MaterialUI】

症状 MaterialUIのTextFieldを実装し、Enterを押したときにページが更新されてしまう事象に遭遇しました。 onKeyDownでeventを見てみようにも、ページが更新されてしまうため、エラーメッセージ自体が消えてしまいます。 以下が該当のソースです。 textField.jsx import React, { Fragment } from 'react'; import TextField from '@material-ui/core/TextField'; export const textField = () => { return( <Fragment> <form className={classes.root} noValidate autoComplete="off"> <TextField id="outlined-basic" label="Email" variant="outlined" fullWidth value={SessionEmailState.user.email} onChange={handleChange} onKeyDown={(event) => { if (event.key === 'Enter') console.log("enterを押しました") } } /> </form> </Fragment> ) } 解決方法 onKeyDownに以下を記述することで解決しました。 おそらくですが、form要素のdefaulteventが原因だと思われます。 formのデフォルトの動作で、指定したURLにformの値を送信するもので、送信先のURLが指定されていなければ現在のURLに送信するようです。 結果的に、現在のURLがリロードしてしまうようです。 なので、以下のようにその動作をしないコードを記述して解決しました。別途Enterしたときにsubmitボタンの動作するようにする場合は、onKeyDownにsubmitを呼ぶようなfunctionを設定してやるとよさそうです。 textField.jsx import React, { Fragment } from 'react'; import TextField from '@material-ui/core/TextField'; export const textField = () => { return( <Fragment> <form className={classes.root} noValidate autoComplete="off"> <TextField id="outlined-basic" label="Email" variant="outlined" fullWidth value={SessionEmailState.user.email} onChange={handleChange} onKeyDown={(event) => { if (event.key === 'Enter') event.preventDefault(); console.log("enterを押しました")           //ここにsubmit用の処理を書くとEnterを押したときに動作してくれる } } /> </form> </Fragment> ) } 参考
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【React】Mapのようにスワイプ移動できるページを実装する

概要 Google Mapのようにドラッグ操作でスワイプできるページを実装します。 https://vw5z8.csb.app/ ドラッグ操作には、Framer Motionを使用します。 スタイリングには、emotion/css(CSS in JS)を使用しています。 実装 下図は実装のイメージです。 screenが移動するのではなく、paperだけが移動すると考えてください。 screenは、ブラウザの表示領域(1vw・1vhの範囲)です。 今回は縦横がscreenの2倍を領域をもつマップを作成したので、paperは2vw・2vhになっています。 containerは、paperの可動域です。screenに表示されるのが、#44B3C2パネルの左上から、#5D4C46パネルの右下までにしたいので、3vw・3vhとなっています。 import { motion } from 'framer-motion'; import React, { useRef, VFC } from 'react'; import { css } from '@emotion/css'; export const MapPage: VFC = () => { const containerRef = useRef<HTMLDivElement>(null) return ( <motion.div ref={containerRef} className={styles.container}> <motion.div className={styles.paper} drag dragPropagation dragConstraints={containerRef}> <div className={styles.panel('#44B3C2')}> <div className={styles.text}>Panel 1</div> </div> <div className={styles.panel('#F1A94E')}> <div className={styles.text}>Panel 2</div> </div> <div className={styles.panel('#E45641')}> <div className={styles.text}>Panel 3</div> </div> <div className={styles.panel('#5D4C46')}> <div className={styles.text}>Panel 4</div> </div> </motion.div> </motion.div> ) } const styles = { container: css` position: relative; width: 300vw; height: 300vh; /* (300 - 100) / 2 */ transform: translate(-100vw, -100vh); display: flex; justify-content: center; align-items: center; `, paper: css` position: absolute; width: 200vw; height: 200vh; display: flex; flex-wrap: wrap; /* start page1 */ top: 100vh; left: 100vw; `, panel: (bgColor: string) => css` width: 50%; height: 50%; background-color: ${bgColor}; display: flex; justify-content: center; align-items: center; `, text: css` color: white; font-size: 3rem; ` } paper(styles.paperを割り当ててるdiv)要素をスワイプさせたいので、ドラッグに関するプロパティを割り当てます。 drag:要素をドラッグできるようにする dragPropagation:親要素をドラッグしたときに子要素も移動するようにする dragConstraints:ドラッグできる領域を決める。今回はcontainer要素を可動域にしたいので、containerRefを割り当てています。 Framer MotionのDragについて詳しく知りたい方は、以下を参照してください。 成果物
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

AWS Amplifyで静的サイトを構築してみた

背景 今年の初めに法人を作ったので、楽天銀行で法人口座を開設しようと手続きを進めてみたら、自社Webサイトがあると提出書類が減るとのことだったので簡易にサイトを構築してみました。 楽天銀行 口座開設に必要な書類 最近PO/PM業務が多かったので久しぶりの技術です。 事前の用意 ドメイン(AWS Route53で取得も可) AWSアカウント githubアカウント 私はmuumuuドメインでドメインを取得、静的サイトはReactで作りました。 構築手順 ほぼここに書かれた内容そのままですが、手順を追って説明します。 静的サイトの構築 まずはローカル環境で静的サイト(Reactアプリ)を作ります。Reactって何?って方はこちらを参照ください。 npx create-react-app mysite cd mysite yarn start githubリポジトリの作成 githubで新しくリポジトリを作成します。 githubへ静的サイトをpush Reactアプリのディレクトリで以下のコマンドを打ちます。環境によって6行目の文字列は異なるのでgithubでリポジトリ作成時に表示されたコマンドをそのまま打ちましょう。 echo "# mysite" >> README.md git init git add README.md git commit -m "first commit" git branch -M main git remote add origin git@github.com:account/mysite.git git push -u origin main githubのデフォルトのブランチがmasterからmainに変わってました。 AWS Amplifyからgithubに接続 Amplifyから、githubで作成したリポジトリへ接続して、Reactアプリをデプロイしてあげます。 Amplifyにアクセスして、いくつかの質問に答えていくだけで設定が終わります。 ここまでくれば、Amplifyのサブドメイン上で、作成したReactアプリがインターネット公開されます。とても簡単ですね。 以前、herokuでもReactアプリをデプロイしたことがありますが、それと比べるととても簡単でした。 ドメイン設定 取得済みのドメインでサイトにアクセスできるようにします。 Route 53のここからホストゾーンの作成をします。 そうすると、ネームサーバー情報が表示されるので、これをドメイン取得サイト(私の場合はmuumuu)に設定します。 ネームサーバー設定の以下の部分にRoute 53で表示されたネームサーバーを入力します。 あとは、Amplifyのドメイン管理からドメインを割り当てます。 設定画面を取り忘れましたが、設定が終わると以下のような画面になります。 以上で作業は完了です。 補足 一部画像が表示されない事象が発生したので調べたら、拡張子をjpegとしているのがだめだったようで。 以下の”書き換えて、リダイレクト”(翻訳が、、、)の設定を書き換えたら表示されるようになりました。 もともとjpgしかなかったところjpegを追加してます。 所感 1-2年技術から離れてから戻ってくると、その進化の速さに驚きます。 静的サイトくらいであればサーバなんて立てる必要もないし、ApacheやらNginxの設定もいらないんですね。。。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【React】レンダリングの最適化にReact.memoとuseCallbackとReact.useMemoを使う

レンダリングの最適化にmemoとuseCallbackとReact.useMemoを使う Reactの開発は、再レンダリングを意識しながら開発をすることで、パフォーマンスの改善につなげることができます。 再レンダリングを制御するためにメモ化を行います。メモ化する技術のReact.memoとuseCallbackとReact.useMemoをまとめていきます。 メモ化の種類 Reactはメモ化することで、再レンダリングを制御・最適化することができます。 メモ化は前回の処理結果を保持しておくことで、処理を高速化することができます。 種類 対象 React.memo コンポーネント useCallback コールバック関数 React.useMemo 変数 再レンダリングが起きる条件 Stateが更新されたコンポーネント Propsが変更されたコンポーネント 再レンダリングされたコンポーネント配下のすべてのコンポーネント  再レンダリングを起こしてみる /src/index.js import ReactDom from "react-dom"; import { App } from "./App"; ReactDom.render(<App />, document.getElementById("root")); ); /src/App.jsx import { useState, useCallback } from "react"; import { Child1 } from "./components/Child1"; import { Child4 } from "./components/Child4"; export const App = () => { console.log("App レンダリング "); const [num, setNum] = useState(0); const onClickButton = () => { setNum(num + 1); }; const onClickReset = useCallback(() => { setNum(0); }, []); return ( <> <button onClick={onClickButton}>ボタン</button> <p>{num}</p> <Child1 onClickReset={onClickReset} /> <Child4 /> </> ); }; /src/components/Child1.jsx import { Child2 } from "./Child2"; import { Child3 } from "./Child3"; const style = { backgroundColor: "#AAFFFF ", }; export const Child1 = (props) => { console.log("Child1 レンダリング "); const { onClickReset } = props; return ( <div style={style}> <p>Child1</p> <button onClick={onClickReset}>リセット</button> <Child2 /> <Child3 /> </div> ); }; jsx/src/components/Child2.jsx const style = { backgroundColor: "#FFCCFF", }; export const Child2 = () => { console.log("Child2 レンダリング "); return ( <div style={style}> <p>Child2</p> </div> ); }; jsx/src/components/Child3.jsx const style = { backgroundColor: "#FFCCFF", }; export const Child3 = () => { console.log("Child3 レンダリング "); return ( <div style={style}> <p>Child3</p> </div> ); }; jsx;/src/components/Child4.jsx const style = { backgroundColor: "#66FF00", }; export const Child4 = () => { console.log("Child4 レンダリング "); return ( <div style={style}> <p>Child4</p> </div> ); }; 上記のコードで実行した後、カウントアップのボタンを押すと下記のようにすべてのコンポーネントが再レンダリングされていることが確認できます。 コンポーネントのメモ化にReact.memoを使う React.memoは、コンポーネントをメモ化します。上記のコードのコンポーネントをReact.memoを使うように変更します。 React.memoの書式 const Component = memo(() =>{}); /src/App.jsx import { useState, memo, useCallback } from "react"; import { Child1 } from "./components/Child1"; import { Child4 } from "./components/Child4"; export const App = memo(() => { // memoに変更した console.log("App レンダリング "); const [num, setNum] = useState(0); const onClickButton = () => { setNum(num + 1); }; const onClickReset = useCallback(() => { setNum(0); }, []); return ( <> <button onClick={onClickButton}>ボタン</button> <p>{num}</p> <Child1 onClickReset={onClickReset} /> <Child4 /> </> ); }); jsx/src/components/Child1.jsx import { memo } from "react"; import { Child2 } from "./Child2"; import { Child3 } from "./Child3"; const style = { backgroundColor: "#AAFFFF ", }; export const Child1 = memo((props) => { // memoに変更した console.log("Child1 レンダリング "); const { onClickReset } = props; return ( <div style={style}> <p>Child1</p> <button onClick={onClickReset}>リセット</button> <Child2 /> <Child3 /> </div> ); }); jsx/src/components/Child2.jsx import { memo } from "react"; const style = { backgroundColor: "#FFCCFF", }; export const Child2 = memo(() => { // memoに変更した console.log("Child2 レンダリング "); return ( <div style={style}> <p>Child2</p> </div> ); }); jsx/src/components/Child3.jsx import { memo } from "react"; const style = { backgroundColor: "#FFCCFF", }; export const Child3 = memo(() => { // memoに変更した console.log("Child3 レンダリング "); return ( <div style={style}> <p>Child3</p> </div> ); }); jsx;/src/components/Child4.jsx import { memo } from "react"; const style = { backgroundColor: "#66FF00", }; export const Child4 = memo(() => { console.log("Child4 レンダリング "); return ( <div style={style}> <p>Child4</p> </div> ); }); メモ化したことで、Appコンポーネントのみ再レンダリングされていることが確認することができました。 関数による再レンダリングを起こしてみる カウンアップをリセットするボタンの関数を作成し、関数をChild1に渡すコードを作成しました。実行し、カウントアップを行うと先程メモ化した、Chile1の再レンダリングが発生してしまいます。 /src/App.jsx import { useState, memo } from "react"; import { Child1 } from "./components/Child1"; import { Child4 } from "./components/Child4"; export const App = memo(() => { console.log("App レンダリング "); const [num, setNum] = useState(0); const onClickButton = () => { setNum(num + 1); }; // 追加しました const onClickReset = () => { setNum(0); }; return ( <> <button onClick={onClickButton}>ボタン</button> <p>{num}</p> <Child1 onClickReset={onClickReset} /> // 関数の受け渡しを追加しました <Child4 /> </> ); }); jsx/src/components/Child1.jsx import { memo } from "react"; import { Child2 } from "./Child2"; import { Child3 } from "./Child3"; const style = { backgroundColor: "#AAFFFF ", }; export const Child1 = memo((props) => { console.log("Child1 レンダリング "); const { onClickReset } = props; return ( <div style={style}> <p>Child1</p> <button onClick={onClickReset}>リセット</button> <Child2 /> <Child3 /> </div> ); }); 関数のメモ化にuseCallbackを使ってみる Reactの関数のメモ化は、useCallbackを使います。onClickReset関数を下記のようにuseCallbackで書きます。第1引数に関数を書き、第2引数には依存配列の要素を書きます。[ ]の場合は、レンダリングされた最初の1回のみ読み込まれます。2回目からは最初に作成されたものが使われます。 /src/App.jsx import { useState, memo, useCallback } from "react"; import { Child1 } from "./components/Child1"; import { Child4 } from "./components/Child4"; export const App = memo(() => { console.log("App レンダリング "); const [num, setNum] = useState(0); const onClickButton = () => { setNum(num + 1); }; const onClickReset = useCallback(() => { //useCallbackを使うように変更した setNum(0); }, []); return ( <> <button onClick={onClickButton}>ボタン</button> <p>{num}</p> <Child1 onClickReset={onClickReset} /> <Child4 /> </> ); }); Child1が、再レンダリングされなくなりました。 変数のメモ化にReact.useMemoを使う 変数や値のメモ化には、React.useMemoを使います。第1引数に計算式、第2引数に依存配列の要素を書きます。依存配列の要素のいずれかが変化した場合にのみメモ化された値を再計算します。下記のコードの場合、aとbの値が変わらない場合、最初にレンダリングした時の値が使い回されます。 React.useMemo const memoizedValue = useMemo(() => { return a + b; }, [a, b]);
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

これからReact始めたい人のための今日だけでできるTODO#22 useContext② コンポーネントの分割

分割したコンポーネントでuseContextを使ってみる 以下のような構成でコンポーネントを作成しAppをProviderでラップしてThirdChildにContextを使って値を渡したいと思います。 App FirstChild SecondChild ThirdChild コンポーネントの作成 作成するファイルは4つです(App.jsはすでにある想定です) - Provider.js - FirstChild.js - SecondChild.js - ThirdChild.js Provider.js Provider.jsのコードは以下の通りになります。 Provider.js import React, { createContext } from 'react'; // 他のファイルでContextを参照できるようにexport export const Context = createContext(); const text = 'Providerから受け取ったテキスト'; // Contextオブジェクトを参照できるように`Provider`でラップ export const Provider = ({ children }) => { return <Context.Provider value={text}>{children}</Context.Provider>; } App.js App.js import { Provider } from './Provider'; import { FirstChild } from './FirstChild'; export default function App() { return ( <> // ProviderでタップしているのでFirstChild配下でContextオブジェクトの値が参照できる <Provider> <FirstChild /> </Provider> </> ); }; FirstChild.js FirstChild.js import { SecondChild } from './SecondChild'; export const FirstChild = () => { return ( <> <p>FirstChild</p> <SecondChild /> </> ); }; SecondChild.js SecondChild.js import { ThirdChild } from './ThirdChild'; export const SecondChild = () => { return ( <> <p>SecondChild</p> <ThirdChild /> </> ); }; ThirdChild.js ThirdChild.js import React, { useContext } from 'react'; import { Context } from './Provider'; export const ThirdChild = () => { const textData = useContext(Context); return ( <> <p>ThirdChild:{ textData }</p> </> ); }; すると画像のようになります。 Provider.jsでvalueに設定した値がThirdChildで受け取り、表示させることができました。 useStateを利用したデータを渡したい 変化するデータを受け渡したい場合も当然出てくると思います。 そんな時は下記のように変更すれば良いと思います。 Provider.js // useStateを追加する import React, { useState, createContext } fron 'react'; // Providerの中でuseStateを定義する export const Provider = ({ children }) => { //追加 const [state, setState] = useState(false); //valueの渡し方を配列に変更 return <Context.Provider value={[state, setState]}>{children}</Context.Provider>; } ThirdChild.js // stateとsetStateを定義してContextオブジェクトから受け取った値を代入する const [state, setState] = useContext(Context); // click時の処理を追加 const handleClick = () => { setState(!state); }; <> <p>ThirdChild:現在のステータス{state ? 'true':'false'}</p> <button onClick={handleClick}>state変更ボタン</button> </> これでクリックしたらステータスによってtrueとfalseのテキスト表示が変わるようになったと思います。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

これからReact始めたい人のための今日だけでできるTODO#21 useContext② コンポーネントの分割

分割したコンポーネントでuseContextを使ってみる 以下のような構成でコンポーネントを作成しAppをProviderでラップしてThirdChildにContextを使って値を渡したいと思います。 App FirstChild SecondChild ThirdChild コンポーネントの作成 作成するファイルは4つです(App.jsはすでにある想定です) - Provider.js - FirstChild.js - SecondChild.js - ThirdChild.js Provider.js Provider.jsのコードは以下の通りになります。 Provider.js import React, { createContext } from 'react'; // 他のファイルでContextを参照できるようにexport export const Context = createContext(); const text = 'Providerから受け取ったテキスト'; // Contextオブジェクトを参照できるように`Provider`でラップ export const Provider = ({ children }) => { return <Context.Provider value={text}>{children}</Context.Provider>; } App.js App.js import { Provider } from './Provider'; import { FirstChild } from './FirstChild'; export default function App() { return ( <> // ProviderでタップしているのでFirstChild配下でContextオブジェクトの値が参照できる <Provider> <FirstChild /> </Provider> </> ); }; FirstChild.js FirstChild.js import { SecondChild } from './SecondChild'; export const FirstChild = () => { return ( <> <p>FirstChild</p> <SecondChild /> </> ); }; SecondChild.js SecondChild.js import { ThirdChild } from './ThirdChild'; export const SecondChild = () => { return ( <> <p>SecondChild</p> <ThirdChild /> </> ); }; ThirdChild.js ThirdChild.js import React, { useContext } from 'react'; import { Context } from './Provider'; export const ThirdChild = () => { const textData = useContext(Context); return ( <> <p>ThirdChild:{ textData }</p> </> ); }; すると画像のようになります。 Provider.jsでvalueに設定した値がThirdChildで受け取り、表示させることができました。 useStateを利用したデータを渡したい 変化するデータを受け渡したい場合も当然出てくると思います。 そんな時は下記のように変更すれば良いと思います。 Provider.js // useStateを追加する import React, { useState, createContext } fron 'react'; // Providerの中でuseStateを定義する export const Provider = ({ children }) => { //追加 const [state, setState] = useState(false); //valueの渡し方を配列に変更 return <Context.Provider value={[state, setState]}>{children}</Context.Provider>; } ThirdChild.js // stateとsetStateを定義してContextオブジェクトから受け取った値を代入する const [state, setState] = useContext(Context); // click時の処理を追加 const handleClick = () => { setState(!state); }; <> <p>ThirdChild:現在のステータス{state ? 'true':'false'}</p> <button onClick={handleClick}>state変更ボタン</button> </> これでクリックしたらステータスによってtrueとfalseのテキスト表示が変わるようになったと思います。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む