YouTubeで公開中
今回作るアプリ
前提
すでにReactプロジェクトを作成済みとします。今回使うのはApp.jsのみです。
メモアプリの概要
今回作成するアプリの機能としては以下の通りです。
- メモの追加
- メモの削除
- メモの編集
- メモの保存
CSSファイル読み込み
今回はReactの解説がメインなので先に作成済みのcssファイルを読み込みます。
App.cssの内容を以下のように書き換えてください
#root {
width: 100%;
height: 100vh;
display: flex;
justify-content: center;
align-items: center;
}
body {
margin: 0;
padding: 0;
background-color: #f0f0f0;
}
.App {
width: 80%;
display: flex;
text-align: left;
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);
background-color: #fff;
border-radius: 8px;
}
.sidebar {
flex: 2;
border-right: 1px solid #ccc;
padding: 20px;
overflow-y: auto;
}
.main {
flex: 8;
padding: 20px;
overflow: hidden;
}
ul {
list-style: none;
padding: 0;
}
li {
margin: 10px 0;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
li.selected {
background-color: #f3f3f3;
font-weight: bold;
}
button {
padding: 10px 20px;
background-color: #007bff;
color: white;
border: none;
border-radius: 4px;
cursor: pointer;
transition: background-color 0.2s ease-in-out;
}
button:hover {
background-color: #0062ca;
}
.delete {
background-color: red;
}
.delete:hover {
background-color: rgb(204, 0, 0);
}
span {
margin-left: 5px;
}
textarea {
width: 100%;
height: 300px;
padding: 15px;
font-size: 16px;
border: none;
border-radius: 4px;
box-sizing: border-box;
resize: none;
}
textarea:focus {
outline: none;
box-shadow: none;
border: none;
}
App.jsファイルでcssファイルを読み込む記述を追加します。
import React from 'react'
import './App.css'; //追加
const App = () => {
return (
<div>App.jsファイルです。</div>
)
}
export default App
まずは見た目を作る
ひとまず機能は置いておいて、メモアプリの見た目を作ります。
見た目の構造としては以下のようになります。
コードで表すと以下のようになります
import React from 'react'
import './App.css';
const App = () => {
return (
//ここから
<div className='App'>
<div className='sidebar'>
<button id="create" >新規作成</button>
<h2>メモ一覧</h2>
<ul>
<li>
<button className='delete'>削除</button>
<span>新規📝</span>
</li>
</ul>
</div>
<div className='main'>
<h2>メモ詳細</h2>
<textarea />
<button className='save'>保存</button>
</div>
</div>
//ここまで追加
)
}
export default App
これで見た目は完成形と同じになったかと思います。
cssを読み込んでいるのでスタイルも適用されているはずです。
メモを新規作成する処理
まずはメモを新規作成する処理を実装しましょう。次のステップで実装します。
メモを管理するstateを定義する
メモはサイドバーでリストとして表示されています。そのひとつ一つのメモを格納するための配列をstateで定義します。先頭でuseStateをインポートしているので忘れず記述してください。
以下を追加してください。
import React from 'react' //削除
import React, { useState } from 'react' //追加
import './App.css';
const App = () => {
const[memos,setMemos] = useState([]); //追加
return (
//既存のコードのため省略
)
}
export default App
Stateについて
const[memos,setMemos] = useState([]);
これがReactでとても重要なstateの定義の仕方です。
stateとは【状態】といういう意味でアプリの中で状態が変化していくものを定義します。
この例で言うとメモは新規作成ボタンを押すたびに新しく作成され、状態が変化しているといえます。
そのためstateで定義しています。
stateの見方としては次のようになります。
const[state名,更新関数] = useState(初期値);
今回初期値として[]と記述しているので初期値は空の配列になります。
これでメモを格納する配列のstateを用意できました。初期値は空で新規作成ボタンを押したときにこの配列にメモを代入していきます。
メモを新規作成する関数の作成
メモを新規作成するにはサイドバーの新規作成ボタンを押します。
jsx内の新規作成ボタンにメモを新規作成する関数を呼び出す記述をしましょう。関数名はaddMemoです。
onClick={addMemo}を追加
<div className='sidebar'>
<button id="create" >新規作成</button> //削除
<button id="create" onClick={addMemo}>新規作成</button> //追加
<h2>メモ一覧</h2>
<ul>
<li>
<button className='delete'>削除</button>
<span>新規📝</span>
</li>
</ul>
</div>
onClick={addMemo}のように記述することで新規作成ボタンをクリックしたときに、addMemo関数を呼び出すことができます。
ではaddMemo関数を定義します。内容は以下の通りです。
import React, { useState } from 'react'
import './App.css';
const App = () => {
const[memos,setMemos] = useState([]);
//ここから
//新規作成ボタンを押したときの処理
const addMemo = () => {
const newMemo = {id: Date.now(), text: "新規📝"};
setMemos([...memos,newMemo]);
console.log(memos);
}
//ここまで追加
return (
//既存のコードの為省略
)
}
export default App
関数内で行っている処理は単純です。
- 新しいメモの作成『 const newMemo = {id: Date.now(), text: “新規📝”}; 』
- 作成したメモをstateとして定義した配列に格納『 setMemos([…memos,newMemo]); 』
- const newMemo={id:Date.now(), text: “新規📝”} について
-
新規作成ボタンが押されたらnewMemoという名前で新しいメモをオブジェクトで定義しています。
メモはidとtextの情報を持っています。idはメモを識別するために利用します。今回はDate.now()とすることで、他とかぶらないユニークな値を取得しています。
textはメモの表示内容です。初期として新規📝を入れています。
- setMemos([…memos, newMemo]); について
-
配列のmemosステイトに新規メモであるnewMemoを代入しています。[…memos, newMemo]という書き方は【スプレッド構文】というものです。Reactではスプレッド構文は良く利用されます。
詳しくは以下の記事が非常に参考になりますJSのスプレッド構文を理解する – Qiita JavaScript/TypeScriptのスプレッド構文(Spread Syntax)のまとめです。なおタイトルではJSといっていますが以下のコードは全てTypeScriptで書いて確認しています…
サイドバーでメモ一覧を表示する
新規作成ボタンを押したときにサイドバーにメモが追加されるようにjsxを編集します。
ulタグの中身を以下のように変更してください。
<ul>
//ここから
{memos.map((memo) => (
<li key={memo.id}>
<button className='delete'>削除</button>
<span>{memo.text}</span>
</li>
))}
//ここまで追加
</ul>
これで新規作成ボタンを押したときにサイドバーにメモが追加されるようになりました。
memosという配列のstateをmap関数でmemoという名前で一つ一つ展開しています。メモは先ほどnewMemoで定義したようにtextというキーを持っているため、memo.textとすることで初期値の【新規📝】が表示されます。
メモ追加処理実行結果↓↓
削除機能の実装
次はメモの削除機能を実装します。削除機能は簡単で、メモが入っているmemos配列から削除するメモを取り除くだけです。
先ほどと同様に削除ボタンに関数を呼び出す記述を追加しましょう。今回はhandleDeleteという削除関数を呼び出します。
<button className='delete'>削除</button> //削除
<button className='delete' onClick={() => handleDelete(memo.id)}>削除</button> //追加
onClick={() => handleDelete(memo.id)
ポイントは関数の引数にmemo.idとしてメモのidを渡していることです。これは、どのメモを削除するかを判断するのに使います。
ではhandleDelete関数を定義します。既存のaddMemo関数の下に記述してください。
//新規作成ボタンを押したときの処理
const addMemo = () => {
//既存のコードの為省略します。
}
//削除ボタンを押したときの処理
const handleDelete = (id) => {
const filterringMemos = memos.filter((memo) => memo.id !== id);
setMemos(filterringMemos)
// 削除後にメモが残っているか確認
if (filterringMemos.length > 0) {
// 新しいメモ配列の最後のメモを選択
const lastMemo = filterringMemos[filterringMemos.length - 1];
setSelectedMemo(lastMemo);
} else {
// メモが一つも残っていない場合の処理
setSelectedMemo(null);
}
}
フィルター関数を使って削除ボタンを押されたメモ以外を抽出して、filterringMemos定数に格納しています。具体的には呼び出し元から送られてきたメモのidとstateで管理しているメモのidを比べて、idが一致していないものだけを抽出しています。そしてその定数をsetMemos(filterringMemos)でstateにセットしています。これによりmemosステイトの中身が削除ボタンを押されたメモ以外になり、削除処理が正常に行われます。
削除処理実行結果↓↓
思ったより長くなりそうなので
YouTubeに解説動画を投稿します。ここまでメモの
- 新規追加
- 削除
の方法を解説していきました。
しかし,これ以降は少し複雑になってくる+長くなりそうなのでYouTubeで解説します
コメント