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

0からはじめたReact

0から始まるReactのお勉強 こんにちは。とある大学3年生です。インターンでReactを使うとのことで0から勉強した際にまとめたものです。誰かのためになれたら幸いです^^ 概要 Reactとは ユーザーのインターフェースを構築するための宣言型で効率的なJSのライブラリ 複雑なUIを「コンポーネント」と呼ばれる小さく独立した部品から組み立てられる。 class ShoppingList extends React.Component { render() { return ( <div className="shopping-list"> <h1>Shopping List for {this.props.name}</h1> <ul> <li>natto</li> <li>daikon</li> <li>osakana</li> </ul> </div> ); } // Example usage: <ShoppingList name="Mark" /> shoppingListはReactコンポーネントクラス、もしくはReactコンポーネント型 コンポーネントはprops(properties)とよばれるパラメータをうけとってrenderメソッドを通じて表示する階層構造を返す state:コンポーネントに何かを覚えさせること Reactコンポーネントはコンストラクタでthis.stateを設定することで状態を持つことができる 子要素同士でやりとりしたりする際に親要素がstateで状態を保存し、親を介してやり取りさせる props:親から子へ渡すことでアプリ内の情報のやりとりをする リファクタリング:ソフトウェアの挙動を変えない範囲で内部構造を整理すること 親要素のコンポーネントが全子要素の状態を保持し、子要素が何を表示するべきかpropsを渡すことで伝える。 このように値を伝えられるだけの子要素(コンポーネント)を制御されたコンポーネントという。 supet()props:JSのクラスではサブクラスのコンストラクタを定義する際にsuperを呼ぶ必要がある。 変化する値へのアプローチ(二種類) ①データの値を直接いじってデータをミューテート(書き換え)する ②望む変更を加えた新しいデータのコピーで古いデータを置き換える←イミュータビリティ イミュータビリティの利点 ①複雑な機能が簡単に実装できる 直接的にデータのミューテートを避けることでゲーム以前のヒストリ(履歴)をそのまま保ってあとで利用できる ②変更の検出 ミュータブルなオブジェクトの中身が直接書き換えられるため変更が検出できない。イミュータブルであると以前のコピーと比較してオブジェクトツリー全体を走査できる ③Reactの再レンダータイミングの決定 Reactでpure componentを構築しやすくなる。コンポーネントをいつ再レンダーすべきか決定しやすい 関数のコンポーネント 関数コンポーネントとは 自分のstateを持たず、renderメソッドだけを有するコンポーネントをよりシンプルに描くための方法。 React.componentを継承するクラスを定義せず、引数をpropsとした関数を書くことができる 関数を基本的に使う。 ex)クラスコンポーネントを関数コンポーネントに変更する クラスコンポーネント class Arasuka extends React.Component { render() { return ( <button className="arasuka" onClick={() => this.props.onClick()} > {this.props.value} </button> ); } } ↓ 関数コンポーネント function Arasuka(props) { return ( <button className="arasuka" onClick={props.onClick}> {props.value} </button> ); } フォーム HTMLのフォーム →ユーザーがフォームにデータを送信したと同時にページが遷移する 制御されたコンポーネント :フォームの送信に応答してフォーム内のデータにアクセスする関数を動かすことができる stateに更新されうる情報を保存、setstateで更新する。 class NameForm extends React.Component { constructor(props) { super(props); this.state = {value: ''}; this.handleChange = this.handleChange.bind(this); this.handleSubmit = this.handleSubmit.bind(this); } handleChange(event) { this.setState({value: event.target.value}); } handleSubmit(event) { alert('A name was submitted: ' + this.state.value); event.preventDefault(); } render() { return ( <form onSubmit={this.handleSubmit}> <label> Name: <input type="text" value={this.state.value} onChange={this.handleChange} /> </label> <input type="submit" value="Submit" /> </form> ); } } 制御されたコンポーネントを使うと、ユーザ入力の値は常に React の state によって制御されるようになります。これによりタイプするコード量は少し増えますが、その値を他の UI 要素に渡したり、他のイベントハンドラからリセットしたりできるようになります React.FCってなに? 関数コンポーネントの型 メモ化 計算結果を保持し、それを再利用すること 「メモ化する」=「計算結果を再利用できるように保持する」 「メモ化された値」=「計算結果が保持された値」 UseMemo メモ化された値を返すフック なぜメモ化された値をつかうのか 値の不要な計算をスキップすることでパフォーマンスの向上につなげる UseMemo構文 useMemo(() => 値を計算するロジック, 依存配列); 依存配列:値を計算するロジックが依存している要素が格納された配列 依存関係 A→R S→R ⇆RはAとSに依存している Reduxとは Reduxとは、React.jsで使用するstateつまりアプリケーションの状態を管理するフレームワーク Reduxの要素 State:アプリケーションの状態 Action:ユーザーが何押したいかという情報を持つオブジェクト Reducer:Actionを元にStateを更新するメソッド Store:Stateの情報を保持している場所 フローチャート ①ActionCreatorsによってactionを作成 ②actionをdispatchする ③Reduccerによってstore内のstateを更新 ④ReactとReduxの連携し、store内のstateをconponentで参照 Reduxを使うメリット Reduxを利用すればどのコンポーネントからも同じ方法でデータの共有ができる Providerコンポーネント ReactのコンポーネントからReduxのstoreにアクセスするために必要となります。 Reduxで共有化したデータにアクセスするためにconnect関数またはuseSelector Hookを利用 containerコンポーネント Container コンポーネント :「Redux の Store から値を注入するためのもの(あとdispatch 関数)」 Refについて Ref は render メソッドで作成された DOM ノードもしくは React の要素にアクセスする方法を提供します いつRefつかうのか フォーカス、テキストの選択およびメディアの再生の管理 アニメーションの発火 サードパーティ(第三者)の DOM ライブラリ(HTMLのツリー構図的な、)との統合 実際につかうところまで ①Refを作成する ②Refにアクセス ref の値はノードの種類によって異なります。(ノード:ツリー構造の点見たいな感じ) ・HTML 要素に対して ref 属性が使用されている場合、React.createRef() を使ってコンストラクタ内で作成された ref は、その current プロパティとして根底にある DOM 要素を受け取ります ・ref 属性がカスタムクラスコンポーネント(自作のコンポーネント)で使用されるとき、ref オブジェクトはコンポーネントのマウントされたインスタンスを current として受け取ります (インスタンス:クラスは一種の雛形であり、同じクラスから作られたインスタンスは同じ変数(プロパティ)と手続き(メソッド)を持つが、各プロパティに代入されるデータ(値)はそれぞれのインスタンスごとに固有となる) ・関数コンポーネント (function components) には ref 属性を使用してはいけません。なぜなら、関数コンポーネントはインスタンスを持たないからです (関数コンポーネントに対して ref が使用できるようにしたい場合は、forwardRef を(必要に応じて useImperativeHandle と組み合わせて)利用するか、コンポーネントをクラスに書き換えます) ③DOM の Ref を親コンポーネントに公開する refのフォワーディング Ref のフォワーディングを使うと、コンポーネントは任意の子コンポーネントの ref を自分自身の ref として公開できるようになります ref のフォワーディングはオプトインの機能であり、それにより、コンポーネントが ref を受け取って、それをさらに下層の子に渡せる useImperativeHandle useImperativeHandle:親コンポーネントに渡されるインスタンス値をカスタマイズするHooksの一つ(関数コンポーネントにメソッドを追加し、それを親コンポーネントから使えるようにするための機能) useImperativeHandleは第三引数に依存配列を渡すことが出来る 正しく使うことで、同じ内容のメソッドを何度も作り直してしまうことを防げる storybookについて storybookとは? UI開発のツール 一度に一つのコンポーネントを操作できる Storybook を使用すると、コンポーネントを再使用するドキュメント化(わかりやすくまとめる)し、コンポーネントを自動的に視覚的にテストしてバグを防ぐことができます。応答性の高いレイアウトを微調整したりアクセシビリティを確認したりするのに役立つアドオンのエコシステムを使用してストーリーブックを拡張します。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Notion BlogをヘッドレスCMSとして、Next.jsで個人ブログを作ってみた

はじめに 年末年始1週間の自由研究として、Next.jsを使って何か作ってみたい…ということで、NotionをヘッドレスCMSとした個人ブログを作ってみました。 せっかくなので制作日記として、 - 作ったものを紹介 - Notion Blogについて - Next.js(React)を使って自分で実装した機能 などまとめておきたいと思います。 ※ヘッドレスCMSとは…従来型のCMS(WordPress等)は入稿画面・DB・表示画面をまとめて管理するのに対し、ここから表示画面を除いたもの。ヘッドレスCMSでは、API経由で取得したコンテンツを基にフロントエンド部分は自前で実装する必要がある。 制作物について 実際に作ったものがこちらです。 構成 構成を簡単に説明すると、 Notion上にブログ記事を保管するDBを作り、Notionで記事を執筆 Next.jsのgetStaticPropsでNotionのAPIを叩いてブログコンテンツを取得 Next.jsでレスポンスを成形してビューに表示 という感じです。 NotionのAPIを叩いてレスポンスを成形する部分は、Notion Blog(詳しくは後述)というOSSのテンプレートをベースに使わせていただきました。 デプロイはVercelで行いました。 実装した機能 MITライセンスのOSSとして公開されているNotion Blog(Vercel社のJJ Kasperさん作)をベースに使用 DBにcategoryのカラムを追加し、NotionのAPIからのレスポンスの成形やビューへの表示をカスタマイズ フロント側での「カテゴリーの選択」「投稿した月の選択」「フリーキーワードによる検索」によるリアルタイム検索機能 記事のカテゴリーに応じてReact iconsでアイコンを表示する CSS Modules UIパーツのコンポーネント化 propsやstateの値により、条件付きレンダリングを行ったりCSSを動的に切り替える Notion Blogについて ベースに使用したNotion Blogというのは、NotionのAPIを叩いてNotionからコンテンツを取得しNext.jsでビューを作ったテンプレートです。 GitHub:https://github.com/ijjk/notion-blog 公式のサンプルページ:https://notion-blog.vercel.app/ こんな感じでシンプルで綺麗なUIをしています。 コードをいじったりしなくても、DeployボタンからVercelに連携し、NotionのDBのID・Tokenを環境変数に設定してVercelでデプロイするだけで、このテンプレート通りの個人ブログが出来るというものです。 Notion Blogでブログコンテンツを取得する仕組み あらかじめNotionで記事を登録するDB(Page, Slug, Published, Date, Authorsの5つの要素を持つインラインテーブル)を作り、このテーブルに記事を入れておきます。 画像引用:https://github.com/ijjk/notion-blog#manually-creating-the-table Notion Blogのソースを見ると、Next.jsのgetStaticPropsでNotionのAPIを叩いてデータベースのコンテンツを取得しています。 使っているのは非公式のAPIで「https://www.notion.so/api/v3」 というエンドポイントを叩いているようです。 Notion Blogを使った理由 Notion 公式のAPI(ベータ版)も2021年5月に公開され、OSSとして公開されているテンプレートで公式APIが使われているものもある中で、Notion Blogを選んだ理由は以下の通りです。 公式のNotion APIはコードブロックに対応していない(もしアップデートを見落としていたらすみません。) 公式のNotion APIでは、コンテンツを取得するだけでなくAPIを使ってNotionのDBへ追加・更新・削除する機能もあるが、これらの機能は不要と思った。 Notion Blogでは、決められた5つのカラムを持つテーブルをNotionで作るだけでテンプレート通りに表示される。簡単!はやい! ざっくりいうと、とりあえず最速・簡単な方法で小さく作って、残った時間でカスタマイズしてみようという感じです。 Notion Blogのセットアップ方法 セットアップ方法は、公式サンプルのページに動画付きで分かりやすく書かれているので省略します。 https://notion-blog.vercel.app/blog/my-first-post Deployボタンからコードを目にすることも無くデプロイすることも出来るようですが、今回はAPIから受け取るレスポンスの成形やUIはカスタマイズする前提だったので、git cloneして編集したうえでデプロイしました。 Notion Blogを使ってみて テンプレートのコードを読んで APIへのリクエストを行うメソッドのファイル切り分け・ディレクトリ構成が分かりやすく、カスタマイズしやすかったです。 Next.jsのダイナミックルーティングを使う際に、ヘッダのメタ情報を出しわける書き方も初めて見て勉強になりました。 ここからは、ブログ記事をブラウザで表示した時の見え方についてです。 画像・動画の挿入 簡単に挿入できるものの、画像のアスペクト比が若干おかしくなっていました…。 動画はNotionで見たまま反映され、再生速度の調整まで出来るのでこれはスゴイ!感激でした。 コードブロックの挿入 公式APIでは対応していないコードブロックも、非公式APIを使っているNotion Blogでは表示できました。 文字色のCSSなんかも自由にカスタマイズできます。 ただしNotion Blogで使っているのは非公式APIなので、 動作が不安定(実際、稀にコンテンツが取得できないという事が起こりました。) 今後このAPIが使えなくなる可能性もある というデメリットはあると思われます。 自分で実装した機能 自分で追加実装した機能や、その他使用技術について書いていきます。 検索機能 カテゴリーで絞り込み・投稿月で絞りこみ・フリーキーワード検索の機能を実装しました。 ページ上部 フッター 【実装手順】 ① APIから取得したブログコンテンツに存在するカテゴリーを配列に格納して、記事が存在する分のカテゴリーボタンを表示。投稿月についても同様。 ② ボタンを押したときや検索欄に入力をした際に発火する絞り込み処理を実装。 フロント側で保持している記事データに対して絞り込みを行い表示を切り替える機能なので、リロードなく瞬時に表示が切り替わります。 検索機能の書き方は非常に勉強になったので、別記事にまとめようと思います。 React Icons 記事のカテゴリーに応じてアイコンを表示しました。 アイコンといえばFontAwesomeと思っていましたが、React用のライブラリがありました。 このライブラリをインストールすると、Font Awesome や Material、Typicons、Codicons(VSCode のアイコン)など色んな種類のアイコンを簡単に利用することができます。 使い方は以下の記事を参考にさせて頂きました。 CSS Modules CSSは、Notion BlogでCSS Modulesが使われていたので、そのままCSS Modulesを使いました。 .module.css で定義したクラス名がそのまま付与されるのではなく、実際はユニークなクラス名が自動的に生成されて付与されることも検証ツールで確認できて、勉強になりました。 Reactのプロジェクト下でのCSSといえば代表的な選択肢は、CSS Modules、styled-component、Tailwindあたりなのかと思いますが、それぞれの違いやメリットデメリットについては正直勉強不足です。。 業務ではTailwindを使っており、今回初めてCSS Modulesを使い、両者の個人的な感想を書いておきます。 Tailwind ファイルの行き来をせずスタイルを確認できて便利。小規模なプロダクトに向いていそう。 CSS Modules コンポーネント単位でスタイルをまとめるという思想なので、コンポーネント指向のReactとの相性は良い(のだと思う)。 スタイルの共通化がしやすくスッキリ整理整頓されている感じで、使いやすかった。 全体の感想 長くなってきたので細かい実装については書きませんが、「実装したい機能がある→どうやったら実現できるか調べる」というプロセスでReact・JavaScriptの書き方も色々勉強になりました。 今回NotionをヘッドレスCMSとして使ってみて、フロントエンドを自前で作るという事は見た目を自由に作れるだけでなく、SG・SSRを使って機能性の高いサイトを作ることが出来ることが大きなメリットだと感じました。 先輩に良いアドバイスもいただいたので、今度はまた他のヘッドレスCMSのサービスを使って個人ブログを作ってみたいなと思います。 参考記事
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【React】ToDoリストを作ってみた

背景 実務でReactも使っているようで、入社前のキャッチアップとしてToDoリストを作成します。 まずは基本的な部分の理解を深めたかったのでJavaScript+Reactで作っていこうと思います。 完成イメージ 今回はあくまでReactの学習に重きをおいているのでHTML/CSSは省きました。 機能としては4つ、それぞれ以下のように動きを区分しました。 1. タスク追加機能 フォームに文字列を入力 追加ボタンをクリックするとタスク追加、追加後はフォームの値を""にする 追加すると、ID、コメント(=タスク名)、状態ボタン、削除ボタンを表示 IDは0から始まる連番 入力後の状態は作業中 2. タスク削除機能 削除ボタンを押すと同じ行のタスクを削除 削除後はID更新 3. タスクの状態変更 "作業中"のときにクリックすると"完了"に更新 "完了"のときにクリックすると"作業中"に更新 4. タスクフィルター機能 ラジオボタン 上のラジオボタンの選択状況を判定 フィルターに応じて表示分け 例: 作業中のラジオボタンが選択されているときは状態が"作業中"のタスクのみ表示 0. 前提 ディレクトリ構造 ディレクトリ構造は以下の通り、最低限のものになりました。 - node_modules - src |- App.jsx |- index.js -package-lock.json -package-json 今回いじるのはApp.jsxのみです! その他のディレクトリについては学習中です、、、 JSXについて jsxというJacaScriptの拡張を使ってReactの要素を生成できるので、React Docsの通りjsxを使って書いていきたいと思います。 JSXの特徴は以下の通り - JavaScriptにHTMLを書ける - マークアップとロジックを両方含むコンポーネントという単位で管理するため - エラーや警告をより多く表示可能 - Reactにとって必須というわけではない(現状、使っている人が多いらしい) プロジェクトの立ち上げ プロジェクトの立ち上げ方は以下を参考にしてください。 React Docs -Create React App プロジェクト立ち上げ npx create-react-app アプリ名 cd アプリ名 ブラウザ表示 npm start index.js import React from "react"; import ReactDOM from "react-dom"; import { App } from "./App"; ReactDOM.render(<App />, document.getElementById("root")); 最後の行の<App />はApp.jsxのことです。 ReactDOM.render(element, document.getElementById("root));とすることでelement(コンポーネント)をレンダーすることができます。 1. タスク追加機能 App.jsx import React, { useState } from "react"; export const App = () => { const [todoText, setTodoText] = useState(""); *1 const [todoList, setNewTodoList] = React.useState([]); // インプットフォームの状態を管理 const onChangeTodoText = (event) => { setTodoText(event.target.value); }; // 追加ボタンを押すとタスクがToDoリストに追加される const onClickAdd = () => { if (todoText === "") return; const newTodo = { comment: todoText, status: "作業中" } // DOMが更新される todoList.push(newTodo); // 入力フォーム内を""にする setTodoText(""); }; return ( <> *2 <div className="task-area"> <h1>ToDoリスト</h1> <table> <thead> <tr> <td >ID</td> <td>コメント</td> <td>状態</td> </tr> </thead> <tbody id="todo-body"> {todoList.map((todo, index) => ( <tr> <td>{index}</td> <td>{todo.comment}</td> <td><button>{todo.status}</button></td> <td><button>削除</button></td> </tr> ))} </tbody> </table> </div> <h2>新規タスクの追加</h2> <div className="add-todo"> <input value={todoText} onChange={onChangeTodoText} /> <button onClick={onClickAdd}>追加</button> </div> </> ); } *1 stateとは現在の状態をあらわすもの。todoTextは現在の状態で、setTodoTextは更新する関数のこと。useState(初期値)`で初期値を設定している。 *2 returnのあとの<></>は、<React.Fragment></React.Fragment>の省略形です。 JSXでは一番上のノードを一つのタグで囲う必要がありますが、余計にタグを使うのも良くないためこのタグが必要です。 2. タスク削除機能 export const App = () => { // todoリスト const [todoText, setTodoText] = useState(""); const [todoList, setNewTodoList] = React.useState([]); // (略) // 削除 const onClickDelete = (index) => { const deletedTodoList = [...todoList]; deletedTodoList.splice(index, 1); setNewTodoList(deletedTodoList); }; return ( <> // (略) <h1>ToDoリスト</h1> <table> <thead> <tr> <td >ID</td> <td>コメント</td> <td>状態</td> </tr> </thead> <tbody id="todo-body">   {todoList.map((todo, index) => (  <tr> <td>{index}</td> <td>{todo.comment}</td> <td><button>{todo.status}</button></td> <td><button onClick={() => onClickDelete(index)}>削除</button></td> // 関数を追加  </tr>   ))} </tbody> </table> </div> // (略) </> ); } splice(n, c) 配列の要素を削除する 引数nは何番目の要素か 引数cはnから数えて何個か onClick={() => 関数(引数)} onClick={関数(引数)}だとレンダリング後すぐに関数が走ってしまうため、この形で回避 ...配列名(スプレット構文) まずは現在のToDoリストを...todoListというスプレット構文で変数に入れます。 削除機能とタスク状態の変更機能はこの配列を更新していく形で実装しています。 3. タスクの状態変更機能 タスクのステータスが"作業中"のときは"完了"に切り替え、 "完了"のときは"作業中"に切り替えるようにしたい。 export const App = () => { // (略) // statusの切り替え const onClickSwitch = (index) => { const switchTodoList = [...todoList]; if (switchTodoList[index].status === "作業中") { switchTodoList[index].status = "完了"; } else if (switchTodoList[index].status === "完了") { switchTodoList[index].status = "作業中"; } setNewTodoList(switchTodoList); }; return ( <> // (略) <h1>ToDoリスト</h1> <table> <thead> <tr> <td >ID</td> <td>コメント</td> <td>状態</td> </tr> </thead> <tbody id="todo-body"> {todoList.map((todo, index) => ( <tr> <td>{index}</td> <td>{todo.comment}</td> <td><button onClick={() => onClickSwitch(index)}>{todo.status}</button></td> <td><button onClick={() => onClickDelete(index)}>削除</button></td> </tr> ))} </tbody> </table> // (略) </> ); } 削除機能と同じように現在の配列をスプレッド構文を使って新たな変数に格納します。 この配列の中にある'status'という要素の状態によって、"作業中"↔"完了"を切り替えるように実装 タスクフィルター機能 export const App = () => { // todoリスト const [todoText, setTodoText] = useState(""); const [todoList, setNewTodoList] = React.useState([]); const [filteredTodoList, setFilteredTodoList] = React.useState([]); const [radio, setRadio] = React.useState('all'); // ラジオボタン更新 const handleChange = (event) => { setRadio(event.target.value); if (event.target.value === "incomplete") { const incompleteTodoList = [...todoList].filter((todo) => todo.status === "作業中"); setFilteredTodoList(incompleteTodoList); } else if (event.target.value === "complete") { const completeTodoList = [...todoList].filter((todo) => todo.status === "完了"); setFilteredTodoList(completeTodoList); } return } // (略) return ( <> <div className="complete-area"> <label> <input type="radio" value="all" onChange={handleChange} checked={radio === 'all'} /> すべて </label> <label> <input type="radio" value="incomplete" onChange={handleChange} checked={radio === 'incomplete'} /> 作業中 </label> <label> <input type="radio" value="complete" onChange={handleChange} checked={radio === 'complete'} /> 完了 </label> <h1>ToDoリスト</h1> <table> <thead> <tr> <td >ID</td> <td>コメント</td> <td>状態</td> </tr> </thead> { radio === "all"? <tbody id="todo-body"> {todoList.map((todo, index) => ( <tr> <td>{index}</td> <td>{todo.comment}</td> <td><button onClick={() => onClickSwitch(index)}>{todo.status}</button></td> <td><button onClick={() => onClickDelete(index)}>削除</button></td> </tr> ))} </tbody> : <tbody id="todo-body"> {filteredTodoList.map((todo, index) => ( <tr> <td>{index}</td> <td>{todo.comment}</td> <td><button onClick={() => onClickSwitch(index)}>{todo.status}</button></td> <td><button onClick={() => onClickDelete(index)}>削除</button></td> </tr> ))} </tbody> } </table> </div> // (略) </> ); } これが一番苦労しました。 大きく分けて以下の3つの機能を実装することにしました。 ラジオボタン handleChange関数でconst [radio, setRadio] = React.useState('all');で初期値を選択し、これでラジオボタンのstateを管理 setRadio(event.target.value);でstateを更新し、クリックされた箇所がチェックされるようにreturn側にもcheckedのプロパティを設定 上のラジオボタンの選択状況を判定 同じくhandleChange関数にラジオボタンの選択状況を判定できるよう、 if (event.target.value === "incomplete")等を書きました。 フィルターに応じて表示分け フィルターされた配列をconst [filteredTodoList, setFilteredTodoList] = React.useState([]);で管理 handleChange関数内でラジオボタンに応じてtodoListの要素が持つstatusでフィルターしました。 最後にradio === "all"? A : B;で表示分け。 完成コード import React, { useState } from "react"; import "./style.css"; export const App = () => { // todoリスト const [todoText, setTodoText] = useState(""); const [todoList, setNewTodoList] = React.useState([]); const [filteredTodoList, setFilteredTodoList] = React.useState([]); const [radio, setRadio] = React.useState('all'); // ラジオボタン更新 const handleChange = (event) => { setRadio(event.target.value); if (event.target.value === "incomplete") { const incompleteTodoList = [...todoList].filter((todo) => todo.status === "作業中"); setFilteredTodoList(incompleteTodoList); } else if (event.target.value === "complete") { const completeTodoList = [...todoList].filter((todo) => todo.status === "完了"); setFilteredTodoList(completeTodoList); } return } // インプットフォームの状態を管理 const onChangeTodoText = (event) => { setTodoText(event.target.value); }; // 追加ボタンを押すとタスクがToDoリストに追加される const onClickAdd = () => { if (todoText === "") return; const newTodo = { comment: todoText, status: "作業中" } // DOMが更新される todoList.push(newTodo); // 入力フォーム内を""にする setTodoText(""); }; // 削除 const onClickDelete = (index) => { const deletedTodoList = [...todoList]; deletedTodoList.splice(index, 1); setNewTodoList(deletedTodoList); }; // statusの切り替え const onClickSwitch = (index) => { const switchTodoList = [...todoList]; if (switchTodoList[index].status === "作業中") { switchTodoList[index].status = "完了"; } else if (switchTodoList[index].status === "完了") { switchTodoList[index].status = "作業中"; } setNewTodoList(switchTodoList); }; return ( <> <div className="complete-area"> <label> <input type="radio" value="all" onChange={handleChange} checked={radio === 'all'} /> すべて </label> <label> <input type="radio" value="incomplete" onChange={handleChange} checked={radio === 'incomplete'} /> 作業中 </label> <label> <input type="radio" value="complete" onChange={handleChange} checked={radio === 'complete'} /> 完了 </label> <h1>ToDoリスト</h1> <table> <thead> <tr> <td >ID</td> <td>コメント</td> <td>状態</td> </tr> </thead> { radio === "all"? <tbody id="todo-body"> {todoList.map((todo, index) => ( <tr> <td>{index}</td> <td>{todo.comment}</td> <td><button onClick={() => onClickSwitch(index)}>{todo.status}</button></td> <td><button onClick={() => onClickDelete(index)}>削除</button></td> </tr> ))} </tbody> : <tbody id="todo-body"> {filteredTodoList.map((todo, index) => ( <tr> <td>{index}</td> <td>{todo.comment}</td> <td><button onClick={() => onClickSwitch(index)}>{todo.status}</button></td> <td><button onClick={() => onClickDelete(index)}>削除</button></td> </tr> ))} </tbody> } </table> </div> <h2>新規タスクの追加</h2> <div className="add-todo"> <input value={todoText} onChange={onChangeTodoText} /> <button onClick={onClickAdd}>追加</button> </div> </> ); } さいごに JavaScriptだとgetElementByIdなどでターゲット要素を指定する必要がありますが、Reactだとevent.target.valueだけでターゲット要素を取得でき、生のJavaScriptで書くよりも圧倒的に簡単に書くことができました。 まだまだコンポーネント化などもできておらず改善点がたくさんありますが、実務でも使いこなせるよう継続して触ってみたいと思います。 参考 React Docs(公式)
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Reactを基本からまとめてみた【21】【Firebase v9を使ったログイン機能の実装③】

機能及び特徴 Email password authentication (Register/Login) Google Sign in Forggot Password Custom Reset password page Protected routes Redirect TO or Back(keeping the state) custom Auth Hook useAuth() Loading indicators while sign-in/up Dark Mode enebled template using Chakra UI Chakra UIとは 公式サイト:Chakra UI ReactのUIコンポーネントライブラリ ダークモードに標準で対応している TypeScriptで書かれている 参考サイト ReactFirebase認証チュートリアル| Firebase9チュートリアル ChakraUIを使用したReactJSのFirebaseAuthentication v9(google / emailサインイン、カスタムリセットパスワード)
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

RapperやBeatMakerを繋ぐサービス「RecPool」が作りたい! 1 ~準備~

RecPoolとは RecPool = 「Recの溜まり場」 Rapper,Beat Makerそしてレコーディングエンジニアを夢見る全てのHIPHOPヘイターの作品つくりの場所(=溜まり場)を提供するサービスです。 時代背景 近年、HIPHOP業界では目まぐるしい変化がおきており、 音声ファイル共有サービスである SoundCloud の爆発的な人気により、 「サウンドクラウドラップ」という言葉で現代のヒップホップにおいて、数多くのラッパーを輩出していきました。 そして驚く事にアメリカ合衆国上院では2021年8月11日を“Hip Hop Celebration Day(ヒップホップ記念日)”、同年8月を“Hip Hop Recognition Month(ヒップホップ認識月間)”、さらに同年11月を“Hip Hop History Month(ヒップホップ歴史月間)”とする決議が全会一致で可決されたとの発表がありました。 (これは国がヒップホップカルチャーがアメリカの歴史における重要な文化の1つとして認められたという事ですね。すごい。。。) By unanimous consent, the Senate passed S.Res.331 (A resolution designating August 11, 2021, as ‘‘Hip Hop Celebration Day’’, designating August 2021 as ‘‘Hip Hop Recognition Month’’, and designating November 2021 as ‘‘Hip Hop History Month’’)— Senate Periodicals (@SenatePPG) July 30, 2021 また、日本国内においても先日までAbemaTVにて土曜日の22時から放送されていた「ラップスタア誕生」では番組内でのフレーズを広瀬アリスさんがツイートしており、いいね数から見てもかなり注目度が高い事が伺えます。 お疲れ様です CYBER RUIです— 広瀬アリス (@Alice1211_Mg) December 7, 2021 話は逸れてしまいましたが、世界ではもちろん日本国内においてもヒップホップカルチャーが熱いという事です! 控え目に言って、ヒップホップは最高です!!!! なぜ作ろうと思ったのか? 作品作りに欠かせない「ラップ部分」「トラックメイキング」「録音や編集そしてミックス」それぞれを最大限まで引き上げるものは「コミュニティの存在」であると思います。 コミュニティに所属する方法としては大きく3つです。 (実際に知り合いのトラックメーカーの子もこんな感じでした) ?地元や先輩・後輩の繋がりやコネ ?イベント会場やクラブハウスで仲良くなる ?Twitter,InstagramそしてSoundCloud等のSNSツールで繋がる コネや才能があれば何とかなりそうですが、 どの方法も初心者や初学者にとっては壁が高く敷居が高いと感じています。 そこで私は、 盛り上がっているヒップホップカルチャーに興味を持ち、ラッパー、トラックメーカー、レコーディングエンジニアを志す初心者や初学者にとって溜まり場に代わるサービスを作成したい! と考え、このサービスを制作する事にしました。 サービスを通じて、 ?Rec経験を積みたいラッパーの支援 ?Rapを載せてみたいトラックメーカーへの支援 ?レコーディング技術 / 表現能力の向上 / モチベーションの維持 に繋がって今より更に熱いHIPHOPシーンのスターが一人でも多く誕生して欲しい限りです。 使用する技術 以下に使用するフレームワークと現時点での理解度および選定理由です。 (?...現時点での理解度 ?...選定理由) ・React.js ?学習中のフレームワークである事からアウトプットとして使用したい ?Vue.jsと比較し、facabookコミュニティによって開発されており信頼性があると考えたため。 ?React,React-Reduxに関するチュートリアルおよび簡単なTODOリストの作成やチャットアプリ作成を行った程度で、実際のアウトプットとしてはポートフォリオサイトを gatsby.js で作成した程度。複雑な状態管理等は扱った事はない為、今回の個人開発で上手くアウトプットして理解を深めたいですね。 ・typescript ?Reactとの相性が良い ?データの単方向性やタイプチェックによって、テスタビリティが高く、品質を保ちやすく堅牢性が高い ?JavaScript自体は仕事の社内管理WEBアプリケーション制作に携わっていたので基礎的な部分(DOM操作/Ajax/axios/非同期処理)を理解しているぐらいです。どちらかと言うとjQueryで書いてた。 typrscriptに関してはReact学習に辺りチュートリアルやドキュメントで初めて触れた程度。実務ではC#をゴリゴリ書いていたので静的型付けで書ける事に感動。 ・Chakra UI ?TypeScript でちゃんと型付けされているから安心して使える点とコンポーネントも豊富である事から デザインセンスがない自分にはピッタリという事で採用。 また既存プロジェクトへの導入はTailwind CSSより面倒みたいですが今回は新規プロジェクトなので関係なし。 ・firebase ?mBassだからサーバーの立ち上げや管理・保守などを気にせずに、クライアントサイドの開発だけに集中できる ?今回はWEB開発だが、アプリ開発の際にデータを共有できるから ?Reactの学習チュートリアルの中で、 Firebase-CLIインストールからinit,build,deployを行ったのみでほとんど触った事がないレベルです。 以下の教材で React × Firebase の基礎学習を行いました。 最速で学ぶFirebase + React Hooks (TypeScript) Firebase + React Hooks(TypeScript)によるWebアプリ開発 次回までに 今年明けに何となく構想はあって学習のアウトプットしたい!と思い立って2日弱くらいでこれくらいしか進みませんでした、、、(泣) 次回までにワイヤーフレームの作成、要件定義、データベース設計、環境構築を行っていこうと思います。仕事からの子供寝かせてからの時間だけですが1週間弱でそれくらいまで行きたいですね。 ズボラなのでMoneybagg yoのscorpioをヘッドホンで聴きながら作業します。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【React】イベントハンドラプロパティ一覧【JavaScript】

はじめに  本記事は、プログラミング初学者が、学習を進めていて疑問に思った点について調べた結果を備忘録も兼ねてまとめたものです。  そのため、記事の内容に誤りが含まれている可能性があります。ご容赦ください。  間違いを見つけた方は、お手数ですが、ご指摘いただけますと幸いです。 イベント属性一覧 Reactで、イベント処理はタグ内にonClickなどのイベントハンドラ用の属性を指定することで定義できます。 Reactでのイベント処理の記述には以下の特徴があります。 イベントは小文字ではなく camelCase で名付けられる イベントハンドラとして文字列ではなく関数を渡す イベント処理を記述する際のイベント属性について以下にまとめます。 // クリック関連 onClick // 要素やリンクをクリックした時に発生 onDblClick // 要素をダブルクリックした時に発生 onMouseDown // マウスでクリックした時に発生 onMouseUp // クリックしたマウスを上げた時に発生 // フォーム関連 onSubmit // フォームを送信しようとした時に発生 onReset // フォームがリセットされた時に発生 onBlur // ページやフォーム要素からフォーカスが外れた時に発生 onFocus // ページやフォーム要素にフォーカスが当たった時に発生 onChange // フォーム要素の選択、入力内容が変更された時に発生 // テキスト関連 onSelect // テキストが選択された時に発生 // キー関連 onKeyUp // 押していたキーをあげた時に発生 onKeyDown // キーを押した時に発生 onKeyPress // キーを押してる時に発生 // 画像読み込み関連 onAbort // 画像の読み込みを中断した時に発生 onError // 画像の読み込み中にエラーが発生した時に発生 onLoad // ページや画像の読み込みが完了した時に発生 // ウィンドウ関連 onUnload // ウィンドウを閉じた時、他のページに切り替えた時、ページをリロード(更新)した時に発生 // マウス関連 onMouseOut // マウスが離れた時に発生 onMouseOver // マウス乗った時に発生 onMouseMove // マウスを動かしている時に発生
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む