20211230のReactに関する記事は6件です。

TailwindCSSでのスムーススクロールの実装

背景と実施したこと Webサイトを構築する際にヘッダーメニューは必ずあると思いますが、今回は同ページの中でスクロールするような動きを実装してみました。 ※以下のようなイメージ 使用しているフレームワークなどの情報は以下の通り next: 12.0.7 react: 17.0.2 TailwindCSS: 3.01 この挙動は「スムーススクロール」と呼ばれるようで、ググる場合はこれがキーワードになると思います。 実装方法としては、これ用のライブラリをインストールすることなくCSSでのみ実装していきます。 (というかそこまで複雑な挙動・実装ではないのでそれで十分) 目次 概要 スムーススクロールの実装(ヘッダーメニューとリンク先) スムーススクロールの実装(CSS) まとめ 概要 今回のサマリーとしては以下の3点がポイントになります。 ヘッダーメニューをクリックしたときに同じページの下部分にスクロールで遷移する挙動を「スムーススクロール」と呼ぶよ。 スムーススクロールはTailwindCSSで超簡単に実装できるよ。 htmlタグにクラスを指定する際は「pages_document.js」を追加する必要があるよ。 スムーススクロールの実装(ヘッダーメニューとリンク先) まず基本的なこととしてスクロールせずに、ただリンクのように飛ばす場合の動きを確認してみてみます。 aタグを活用して以下のように記述することで同ページ内での遷移を実現します。 メニュー(リンク元) <a href="#about">about</a> リンク先 <h2 id='about' className=' text-[#384359] text-center font-bold text-xl p-16 '>私について</h2> ハッシュ(#)の後に飛ばしたリンク先のIDを指定することで紐づきができます。 next.jsなのでJSXを活用して実際のコードを書くと以下のようになるイメージです。 map関数の使い方に関しては、以下の記事も合わせて参照いただくとよいかもです。 next.jsにおけるmapの使い方と「Each child in a list should have a unique "key" prop」の対応 header.js export default function Layouut() { const menuList = [ { name: 'about', link: '#about' }, { name: 'skills', link: '#skills', }, { name: 'values', link: '#values', }, { name: 'future', link: '#future', }, ]; return ( <> <Header list={menuList}></Header> <main> <Main /> <About /> <Skill /> <Values /> <Future /> </main> <Footer /> </> ); } header.js export default function Header(props) { const [openMenu, setOpenMenu] = useState(false); console.log(openMenu); const data = props.list; console.log(data); const menuFunction = () => { setOpenMenu(!openMenu); }; return ( <nav className='flex'> <div className='flex-none sm:flex-1 md:flex-1 lg:flex-1 xl:flex-1'> <Link href='/'> <a> <Image src='/images/logo.png' alt='logo' width={200} height={100} /> </a> </Link> </div> {openMenu ? ( <div className='flex flex-row absolute z-10 top-0 right-0 min-h-full min-w-full '> <div className='basis-1/2 bg-gray-400/50'></div> <div className='basis-1/2 bg-white'> <ul className=' text-center'> <li className='p-2 '> <button onClick={menuFunction} className='font-bold'> close </button> </li> {data.map((value, index) => ( <li key={index} className='p-2 '> <a href={value.link} onClick={menuFunction}> {value.name} </a> </li> ))} </ul> </div> </div> ) : undefined} <div className='flex-initial text-[#abc5c5] font-bold m-5 '> <ul className='md:flex hidden flex-initial text-left'> {data.map((value, index) => ( <li key={index} className='p-4'> <a href={value.link}>{value.name} </a> </li> ))} </ul> </div> <button onClick={menuFunction} className='flex-initial absolute top-0 right-1 md:hidden'> <Image src='/images/menu.png' alt='logo' width={50} height={50} /> </button> </nav> ); } スムーススクロールの実装(CSS) 次に、いよいよスクロールの動きを実装していきます。 といってもこれはTailwindCSSでは「scroll-smooth」として標準で用意されているので、これをHTMLの最上位である htmlタグに適用してあげるだけです。 ※TailwindCSSの導入に関しては以下を参照ください。 TailwindCSS ver3.0の導入について ただし、気を付けなければいけないのが、htmlタグやbodyタグのようなすべての要素に対して普遍的に影響があるタグの場合は 「custom Document」と呼ばれる別のファイルを生成する必要があるという点です。 詳細は以下を参照 custom Documentとは ということで、pages配下に「_document.js」を作成します。 さらにその中のHtmlコンポーネントにクラスとして「scroll-smooth」を指定します。 src\pages\_document.js import Document, { Html, Head, Main, NextScript } from 'next/document'; class MyDocument extends Document { static async getInitialProps(ctx) { const initialProps = await Document.getInitialProps(ctx); return { ...initialProps }; } render() { return ( <Html className='scroll-smooth'> <Head /> <body> <Main /> <NextScript /> </body> </Html> ); } } export default MyDocument; 以上で実装は完了です。 htmlタグを補強するためには_document.jsを作成するというところが私にとっては一番の学びでした。 next.jsのお作法も覚える必要がありますね。 まとめ あらためておさらいをすると以下がポイントです。 ヘッダーメニューをクリックしたときに同じページの下部分にスクロールで遷移する挙動を「スムーススクロール」と呼ぶよ。 スムーススクロールはTailwindCSSで超簡単に実装できるよ。 htmlタグにクラスを指定する際は「pages_document.js」を追加する必要があるよ。 余談ですが、TailwindCSSの2系ではスムーススクロールは拡張機能を位置づけだったようですね。 非常に便利なので、今後のver-upに期待します。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

2021年総括まとめ

目的 2022年さらに活用できるための備忘メモ用 年内のおさらい 技術メモまとめ 試したこと 1. Docker MatterMost をここでは題材にしています。 git clone https://github.com/mattermost/mattermost-docker-preview.git Dockerfile # Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved. # See License.txt for license information. FROM mysql:5.7 RUN apt-get update && apt-get install -y ca-certificates # # Configure SQL # ENV MYSQL_ROOT_PASSWORD=mostest ENV MYSQL_USER=mmuser ENV MYSQL_PASSWORD=mostest ENV MYSQL_DATABASE=mattermost_test # # Configure Mattermost # WORKDIR /mm # Copy over files ADD https://releases.mattermost.com/6.0.0/mattermost-team-6.0.0-linux-amd64.tar.gz . RUN tar -zxvf mattermost-team-*-linux-amd64.tar.gz ADD config_docker.json ./mattermost/config/config_docker.json ADD docker-entry.sh . RUN chmod +x ./docker-entry.sh ENTRYPOINT ./docker-entry.sh # Mattermost environment variables ENV PATH="/mm/mattermost/bin:${PATH}" # Create default storage directory RUN mkdir ./mattermost-data VOLUME /mm/mattermost-data # Ports EXPOSE 8065 dockerがインストール済みであれば、以下コマンドで起動完了 docker run --name mattermost-preview -d --publish 8065:8065 mattermost/mattermost-preview 2. VBA Do Until 文を極めれば、いろいろツールが作れる Dim row As Integer row = 2 Do Until Cells(row, 1).Value = "" Cells(row, 5).Value = Cells(row, 3).Value * Cells(row, 4).Value row = row + 1 Loop No列は固定となるので、それを軸にすることで、楽にツール化できる。 3. JsRender.js Reactを使わない環境では、JqueryやNode.jsと共に使われるケースが多い。 https://www.jsviews.com/ 読み込みに必要なもの <!-- Load jQuery --> <script src="https://code.jquery.com/jquery-3.5.1.js"></script> <!-- Load JsRender latest version, from www.jsviews.com: --> <script src="https://www.jsviews.com/download/jsrender.js"></script> 実装サンプル <!-- 1.レンダリングされる最終的な箱の用意 --> <div id="result"></div> <!-- 2.レンダリング情報の宣言 --> <script id="myTmpl" type="text/x-jsrender">{{:name}}</script> <!-- 3.具体的なJSの中身 --> <script> var tmpl = $.templates("#myTmpl"); var data = {name: "Jo"}; var html = tmpl.render(data); // テンプレート(tmp1)にデータがレンダリングされる $("#result").html(html); // ←ここで初めて「1」のDOMに出力される </script> 4. React.js と Webpack そもそもReact.jsってなんだよ? ググるといろいろ出てきますが、一言でいうと「古DOMと新DOMの差分から、更新したいDOMだけを見極めて、ブラウザにレンダリング情報をセクションとしてコンポーネント単位等でDOMに流し込むことができる。」 Reactインストール $ npm install react react-dom $ npm install -D @babel/preset-react node.js って npm とは Node Package Manager の略。 JavaScript 系のパッケージを管理するツール。 必要とするパッケージをインストールする際、依存するパッケージもまとめてインストールしてくれる。 node.jsの初期編としては、まず... npm init などで作成したpackage.jsonを基準に、npm installを実施して、node_moduleのディレクトリ作成される。 package.josn { "name": "myProject", "version": "1.0.0", "description": "", "main": "index.js", //←エントリポイント "scripts": { "test": "echo \"Error: no test specified\" && exit 1", "build”: "webpack --mode production", "dev”: "webpack --watch", }, "keywords": [], "author": "", "license": "ISC" } webpack 複数のモジュールを1つにまとめて出力できる。モジュールバンドラ。 loderを用いることでjsファイル以外をまとめることができる。 Webpack インストール $ npm install -D webpack webpack-cli webpack-dev-server html-webpack-plugin Babelインストール $ npm install -D @babel/core @babel/runtime @babel/plugin-transform-runtime @babel/preset-env babel-loader Babel本体とプラグイン、プリセットの設定、webpackのローダーをインストール。 TypeScriptを使用する $ npm install -D typescript ts-loader @babel/preset-typescript @types/react @types/react-dom tsconfig.json { "compilerOptions": { "target": "esnext", "jsx": "react", "forceConsistentCasingInFileNames": true, "strict": true, "noImplicitAny": true, "strictNullChecks": true, "noUnusedLocals": true, "noUnusedParameters": true, "noImplicitReturns": true, "moduleResolution": "node", "esModuleInterop": true, "isolatedModules": true, "allowSyntheticDefaultImports": true, }, "include": ["src/**/*.ts", "src/**/*.tsx"], "exclude": ["node_modules"] } ビルド $ npm run build $ webpack --watch ←WATCHモードとはビルド対象のファイルに変化があった場合に検知して、自動的に再ビルドしてくれる機能のことです。(一言でいうと修正してすぐ反映) ビルド&実行 $ npx webpack serve --config webpack.config.js webpack.config.js const path = require("path"); const HtmlWebpackPlugin = require("html-webpack-plugin"); module.exports = { mode: "development", entry: path.resolve(__dirname, "src/app.tsx"), // エントリーポイント修正 output: { path: path.resolve(__dirname, "dist"), filename: "app.js", }, resolve: { modules: [path.resolve(__dirname, "node_modules")], extensions: [".js", ".ts", ".tsx"], // ts, tsx 追加 }, module: { rules: [ { test: [/\.ts$/, /\.tsx$/], use: [ { loader: "babel-loader", options: { presets: ["@babel/preset-env", "@babel/preset-react", "@babel/preset-typescript"], // typescript追加 }, }, 'ts-loader' // ts-loader追加 ], }, ], }, plugins: [ new HtmlWebpackPlugin({ template: path.resolve(__dirname, "src/index.html"), }), ], }; JSのテストツール JEST などでテストメソッドを作成し、検証ができる。 5. Spring と Junit Spring の話は略します Junit ValidationTest1.java @ParameterizedTest @ValueSource(strings = {"Java", "java", "JAVA"}) void upperCase(String s) { assertEquals("JAVA", s.toUpperCase()); } SampleTest1.java @Test public void testJudgeGrade() { System.out.println("judgeGrade"); int score = 0; Score instance = new Score(); String expResult = ""; String result = instance.judgeGrade(score); assertEquals(expResult, result); // TODO review the generated test code and remove the default call to fail. fail("The test case is a prototype."); } Mockito Mockitoは、Javaのユニットテストのために開発されたモックフレームワーク(mocking framework)です。テストでモックオブジェクトを直感的に操作できるのを目的として開発されています。 モックオブジェクトはテスト対象(テストしたいクラス)から呼び出される依存先のオブジェクトに代わって使用されるテスト用のオブジェクトです。 スタブ メソッドの実行に対して、事前に定義された振る舞い(引数、返り値)を提供するオブジェクト モック メソッドの実行に対して、実行回数やパラメータの呼び出しを記録するオブジェクトです。 スパイ メソッドの実行に対して、実行回数やパラメータの呼び出しを記録するオブジェクトです。モックとの違いとして、基本的な定義では、モックはメソッドの実行中に検証するのに対して、スパイはメソッドの実行後に検証するという違いがあります。しかし、Mockitoで扱う検証メソッドではメソッドの実行後に検証するので両者の違いはありませんが、Mockitoにおけるスパイはオブジェクトを部分的にモックする用途で使用されています。 使用方法 テスト対象のクラスに @InjectMocks をつける テスト対象のクラス内で呼ばれるクラスに @Mock をつける 前処理(@BeforeEach)に、@Mock のモックオブジェクトを初期化する XxxYyyyServiceTest.java @Before public void init() { //@Mockアノテーションのモックオブジェクトを初期化 //これを実行しないと@Mockアノテーション、@InjectMocksを付与した //Mockオブジェクトが利用できない MockitoAnnotations.initMocks(this); //Mockの設定 //mapper.findAll()メソッドを実行した際の戻り値をここで設定 when(mapper.findAll()).thenReturn(makeUserDataList()); } @Test をつけたメソッド内でInjectMocksした(テスト対象メソッド)を実行する assertEquals 等でモックの結果と期待結果を比較 最後に 2022年は、自身の強みをさらに伸ばして、かつできなかったところを総復習し、 案件で活躍していきたいですね。良いお年を...
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

React + Reduxを基本からまとめてみた【8】【Redux Middleware】

参考サイト React/ReduxでGoogleカレンダー風カレンダーアプリケーションを作ろう
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

React + Reduxを基本からまとめてみた【8】【】

Reduxとは 『redux』とは、フロントエンドにおける状態管理に特化したライブラリ。 react の state の限界 小規模なアプリケーションであれば、もちろん1つの『state』でも十分に管理できるが、大きなアプリケーションになると、コンポーネントツリーは肥大化し、状態管理が複雑になる。 もし、親コンポーネントで状態を一限管理しようとするととても大きな『state』になってしまい、状態の更新や取得が複雑になりバグの原因となる。 また、バケツリレーが至るところで起こってしまうのも管理が大変になる。 また、それぞれのコンポーネントで独自の『state』を持ってしまうと、他のコンポーネントにその状態を知らせるのが難しくなり複雑化する。 redux で状態を分離する 『redux』を使うことで状態管理にかかる部分をコンポーネントのツリーから分離することができる。煩雑なバケツリレーからの解放(完全に解放されるわけではないが幾分ましになる)やコンポネート間での状態のやりとりが可能になる。 redux の特徴 『redux』は『flux』という概念に基づいて設計されている。『flux』とは一方向に状態が流れるというという特徴を持っている。また、値を直接変更しないという関数型の特徴も併せ持っている。 Redux の用語解説 action type reducer や middlware(後述)がどの処理を行うかを判断するために使われる。 直接値を変更できないのでこのような方法が取られる。定数や typescript であれば enum で定義されることが多い。 const ACTION_TYPE = "ACTION_TYPE"; action 「どんな処理をするのか(= action type)」と「それに必要な引数(= payload)」が入ったオブジェクトを返す関数。view 側からこの action を dispatch(= redux に通知)することで redux のフローが実行されるという仕組み。 action は純粋関数である必要があり、非同期処理などの副作用がある処理を行ってはいけない。 const actionName = payload => ({ type: ACTION_TYPE payload }); 参考サイト React/ReduxでGoogleカレンダー風カレンダーアプリケーションを作ろう
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

React + Reduxを基本からまとめてみた【8】【Redux総合】

Reduxとは 『redux』とは、フロントエンドにおける状態管理に特化したライブラリ。 react の state の限界 小規模なアプリケーションであれば、もちろん1つの『state』でも十分に管理できるが、大きなアプリケーションになると、コンポーネントツリーは肥大化し、状態管理が複雑になる。 もし、親コンポーネントで状態を一限管理しようとするととても大きな『state』になってしまい、状態の更新や取得が複雑になりバグの原因となる。 また、バケツリレーが至るところで起こってしまうのも管理が大変になる。 また、それぞれのコンポーネントで独自の『state』を持ってしまうと、他のコンポーネントにその状態を知らせるのが難しくなり複雑化する。 redux で状態を分離する 『redux』を使うことで状態管理にかかる部分をコンポーネントのツリーから分離することができる。煩雑なバケツリレーからの解放(完全に解放されるわけではないが幾分ましになる)やコンポネート間での状態のやりとりが可能になる。 redux の特徴 『redux』は『flux』という概念に基づいて設計されている。『flux』とは一方向に状態が流れるというという特徴を持っている。また、値を直接変更しないという関数型の特徴も併せ持っている。 Redux の用語解説 action type reducer や middlware(後述)がどの処理を行うかを判断するために使われる。 直接値を変更できないのでこのような方法が取られる。定数や typescript であれば enum で定義されることが多い。 sample.js const ACTION_TYPE = "ACTION_TYPE"; action 「どんな処理をするのか(= action type)」と「それに必要な引数(= payload)」が入ったオブジェクトを返す関数。view 側からこの action を dispatch(= redux に通知)することで redux のフローが実行されるという仕組み。 sample.js const actionName = payload => ({ type: ACTION_TYPE payload }); ※action は純粋関数である必要があり、非同期処理などの副作用がある処理を行ってはいけない。 正確には、『action type』と『payload』を含むオブジェクトが『action』 で、その 『action』オブジェクトを返す関数は『action creator』と呼ばれている。毎回、同じようなオブジェクトを定義するのが煩雑なのでこのような記述方法が一般的。ライブラリ等を使ってもっと簡単に実装する方法もあるが、実装の意味を理解するためにもあえてフルスクラッチで実装している。 reducer payload と直前の state を受け取って次の state を返す関数で、redux におけるstoreは reducer を介さないと更新できない仕組みになっている。どのように状態を更新するかは action type で条件分岐をするのが一般的。 sample.js const reducer = (state = initState, { type, payload }) => { switch (type) { case ACTION_TYPE: return newState(payload); default: return state; } }; middleware 基本的に非同期の処理(詳細には副作用のある処理)を行うところで、redux 自体には非同期を処理する機能は備わっていないので別のライブラリ(redux-thunk, redux-saga, redux-observable など)を使うのが一般的。 『middeware』の関数はその内部で他の dispatch を行うことができる。よくある使われ方としては、非同期処理が解決されるまで待って解決されたらその値を dispatch するという使い方で、サーバーからのデータの取得や更新などで頻繁に行われる。 view から直接 middleware の関数を呼んだり、middlreware の処理を発火させるための action を実行する。この呼び出し方は使うライブラリによって異なる。 store コードで直接的に記述する部分はほとんどないが、redux の状態そのものは store と呼ばれるオブジェクトで、この中に各 reducer に対応した state がネストして入っている。reducer を介してしか変更のできない immutable なグローバル変数。 グローバル変数で状態を管理すると色々なところから変更ができて大変なことになるが、 それを immutable という制約で解決しているのが redux。redux のアーキテクチャに乗っ取ることで安全にグローバルスコープの変数が使えるようになる。 react-redux 『redux』は実は react のためだけのライブラリではなく、redux 自体は react に対するインターフェイスを持っていない。redux の react に対するインターフェイスを提供するのが react-redux というライブラリである。『react-redux』 は『Provider』と『connect』という関数を持っている。 Provider react がどの store を使うのかを定義するためのもので、多くの場合はルート階層のコンポーネントをこの『Provider』でラップして、それより下のコンポーネントでその store が使えるようにする。store は単に状態が保管されている場所ぐらいの認識でOK。 重要なポイントは『Provider』でラップしただけではコンポーネントは store が持っている状態について知ることができないし redux に対して何もできないということ。 下記で、説明するconnectを使うことで初めてコンポーネントは store から必要なデータを取得したり状態の更新を redux に対して要求(= dispatch)することができるようになる。 connect 各コンポーネント単位でどの state を参照してどの dispatch を実行するのかを定義するための関数。 高階関数になっていて、適用したいコンポーネントとどのデータを props として渡すのかを定義した関数を引数にとる。 sample.js const mapStateProps = ({ count }) => ({ count }); const mapDispatchProps = dispatch => ({ increment: count => dispatch(increment(count)), decrement: count => dispatch(decrement(count)) }); このように書けば props に redux の情報を渡すことができるという理解でOK。 なぜProviderとconnectがあるのか 保守性が低くなる これは、state のスコープが限定されないために起こりうる問題で、どこからでも簡単に参照できてしまうので、どこか他のところを変更したときにどこまで影響が及ぶのかが予測しづらくなる。 もし『connect』があると、state が参照できるスコープを制限することができるので、被害も最小限に抑えられる。 バケツリレーが煩雑になる どこでも、参照できるとは言っても結局は『Provider』でラップされたそのコンポーネントしか状態について知ることはできないので、それ以下のコンポーネントに関してはバケツリレーをしていくしか解決法がない。 これでは、そもそも redux を使わなかったパターンと変わらないので、やはりconnectは必要である。 参考サイト React/ReduxでGoogleカレンダー風カレンダーアプリケーションを作ろう
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【React】モーダルの作成方法【入門】

はじめに  本記事は、プログラミングの学習を始めて1ヶ月の初学者が、学習を進めていて疑問に思った点について調べた結果を備忘録も兼ねてまとめたものです。  そのため、記事の内容に誤りが含まれている可能性があります。ご容赦ください。  間違いを見つけた方は、お手数ですが、ご指摘いただけますと幸いです。 React 入門 Reactとは Facebook社(現 Meta Platforms)が開発したUIパーツを構築するためのJavaScriptライブラリです。 モーダルの作成 以下のように記述することでモーダルを作成することができます。 App.js import React from 'react'; import Lesson from './Lesson'; class Main extends React.Component { render() { const lessonList = [ { name: '~~~~', image: '#', introduction: '~~~~~~~~~~', }, { name: '~~~~', image: '#', introduction: '~~~~~~~~~~', }, { name: '~~~~', image: '#', introduction: '~~~~~~~~~~', }, { name: '~~~~', image: '#', introduction: '~~~~~~~~~~', }, ]; return ( <div className='main-wrapper'> <div className='main'> <div className='copy-container'> <h1>ああああああ。</h1> <h2>ああああああ。</h2> </div> <div className='lesson-container'> <h3>ああああああ。</h3> {lessonList.map((lessonItem) => { return ( <Lesson name={lessonItem.name} image={lessonItem.image} introduction={lessonItem.introduction} /> ); })} </div> </div> </div> ); } } export default Main; Lesson.js import React from 'react'; class Lesson extends React.Component { constructor(props) { super(props); this.state = {isModalOpen: false}; } handleClickLesson() { this.setState({isModalOpen: true}); } handleClickClose() { this.setState({isModalOpen: false}); } render() { let modal; if (this.state.isModalOpen) { modal = ( <div className='modal'> <div className='modal-inner'> <div className='modal-header'></div> <div className='modal-introduction'> <h2>{this.props.name}</h2> <p>{this.props.introduction}</p> </div> <button className='modal-close-btn' onClick={() => {this.handleClickClose()}} > とじる </button> </div> </div> ); } return ( <div className='lesson-card'> <div className='lesson-item' onClick={() => {this.handleClickLesson()}} > <p>{this.props.name}</p> <img src={this.props.image} /> </div> {modal} </div> ); } } export default Lesson;
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む