<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>TODOアプリ &#8211; ケケンタの独学ITブログ</title>
	<atom:link href="https://kekenta-it-blog.com/tag/todo%E3%82%A2%E3%83%97%E3%83%AA/feed/" rel="self" type="application/rss+xml" />
	<link>https://kekenta-it-blog.com</link>
	<description>プログラミングやWeb制作の情報を発信</description>
	<lastBuildDate>Thu, 24 Jul 2025 06:23:35 +0000</lastBuildDate>
	<language>ja</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	<generator>https://wordpress.org/?v=6.9.4</generator>

<image>
	<url>https://kekenta-it-blog.com/wp-content/uploads/2023/07/cropped-KEKENTA-BLOG-32x32.png</url>
	<title>TODOアプリ &#8211; ケケンタの独学ITブログ</title>
	<link>https://kekenta-it-blog.com</link>
	<width>32</width>
	<height>32</height>
</image> 
	<item>
		<title>【React】初心者向けTODOアプリ開発シリーズ &#8211; 完全ガイドまとめ</title>
		<link>https://kekenta-it-blog.com/react-todo-app-series-complete-guide-summary/</link>
					<comments>https://kekenta-it-blog.com/react-todo-app-series-complete-guide-summary/#respond</comments>
		
		<dc:creator><![CDATA[ケケンタ]]></dc:creator>
		<pubDate>Tue, 22 Jul 2025 11:42:16 +0000</pubDate>
				<category><![CDATA[React]]></category>
		<category><![CDATA[Javascript]]></category>
		<category><![CDATA[TODOアプリ]]></category>
		<category><![CDATA[開発シリーズ]]></category>
		<guid isPermaLink="false">https://kekenta-it-blog.com/?p=15557</guid>

					<description><![CDATA[<p><img src="https://kekenta-it-blog.com/wp-content/uploads/2025/07/eye-catch__react-todo-app-series-complete-guide-summary__15557-1024x576.jpg" class="webfeedsFeaturedVisual" /></p>この記事では、当ブログで公開しているReact初心者向けTODOアプリ開発シリーズをご紹介します。 基本編（第1回〜第7回）は既に公開済みで、発展編（第1回〜第5回）はこれから順次執筆していく予定です。  記事一覧はこち [&#8230;]]]></description>
										<content:encoded><![CDATA[<p><img src="https://kekenta-it-blog.com/wp-content/uploads/2025/07/eye-catch__react-todo-app-series-complete-guide-summary__15557-1024x576.jpg" class="webfeedsFeaturedVisual" /></p><div class="swell-block-balloon"><div class="c-balloon -bln-left" data-col="gray"><div class="c-balloon__icon -circle"><img decoding="async" src="data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==" data-src="https://kekenta-it-blog.com/wp-content/uploads/2023/07/キリッ-150x150.jpg" alt="" class="lazyload c-balloon__iconImg" width="80px" height="80px"><noscript><img decoding="async" src="https://kekenta-it-blog.com/wp-content/uploads/2023/07/キリッ-150x150.jpg" alt="" class="c-balloon__iconImg" width="80px" height="80px"></noscript><span class="c-balloon__iconName">ケケンタ</span></div><div class="c-balloon__body -speaking -border-on"><div class="c-balloon__text">
<p>こんにちは！　ケケンタです。</p>
<span class="c-balloon__shapes"><span class="c-balloon__before"></span><span class="c-balloon__after"></span></span></div></div></div></div>


<p>この記事では、当ブログで公開している<strong>React初心者向けTODOアプリ開発シリーズ</strong>をご紹介します。</p>



<p class="is-style-icon_pen">基本編（第1回〜第7回）は既に公開済みで、発展編（第1回〜第5回）はこれから順次執筆していく予定です。</p>



<p><strong><a href="#anc-posts-list"><span data-icon="LsChevronDown" data-id="0" style="--the-icon-svg: url(data:image/svg+xml;base64,PHN2ZyBoZWlnaHQ9IjFlbSIgd2lkdGg9IjFlbSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiBhcmlhLWhpZGRlbj0idHJ1ZSIgdmlld0JveD0iMCAwIDQ4IDQ4Ij48cGF0aCBkPSJtMjIuOSAzMy0xMy0xMy4xYy0uOC0uOC0uOC0yIDAtMi44LjgtLjggMi0uOCAyLjggMEwyNCAyOC40bDExLjMtMTEuM2MuOC0uOCAyLS44IDIuOCAwIC44LjguOCAyIDAgMi44TDI1LjEgMzNjLS42LjYtMS42LjYtMi4yIDB6Ij48L3BhdGg+PC9zdmc+)" aria-hidden="true" class="swl-inline-icon"> </span>記事一覧はこちら</a></strong></p>



<h2 class="wp-block-heading">シリーズ概要</h2>



<h3 class="wp-block-heading">シリーズの目的</h3>



<p>初心者から実践的なReact開発者への成長を目指し、段階的に学習を進めていきます。最終的にはデータベース連携ができる本格的なTODOアプリを完成させることが目標です。</p>



<h3 class="wp-block-heading">学習の流れ</h3>



<ul class="wp-block-list is-style-num_circle -list-under-dashed">
<li><strong>基本編（第1回〜第7回）</strong>: Reactの基礎から完全なCRUD操作まで</li>



<li><strong>発展編（第1回〜第5回）</strong>: より高度な機能と実践的な開発スキル</li>
</ul>



<h3 class="wp-block-heading">最終成果物</h3>



<p>データベース連携ができる本格的なTODOアプリケーション</p>



<h3 class="wp-block-heading">対象読者</h3>



<ul class="wp-block-list is-style-check_list -list-under-dashed">
<li>React初心者の方</li>



<li>実践的なアプリケーション開発を学びたい方</li>



<li>段階的にスキルアップしたい方</li>
</ul>



<h2 class="wp-block-heading">なぜ今Reactを学ぶべきなのか</h2>



<p>生成AIが急速に発展し、フロントエンド開発の自動化が進んでいる現在でも、Reactの重要性は衰えるどころか、むしろ高まっています。</p>



<p>ChatGPTやGitHub CopilotなどのAIツールがフロントエンドコードを生成する際にも、Reactが採用されていることがしばしば。AIという比較的新しい分野においても、Reactは活躍しているのです。</p>



<h3 class="wp-block-heading">Reactが選ばれ続ける理由</h3>



<ul class="wp-block-list is-style-good_list -list-under-dashed">
<li><strong>豊富な学習リソース</strong>: 大量のチュートリアル、ドキュメント、コミュニティサポート</li>



<li><strong>安定したエコシステム</strong>: 長年の実績と継続的な改善</li>



<li><strong>高い求人需要</strong>: 世界中の企業でReact開発者が求められている</li>



<li><strong>AIとの相性</strong>: 生成AIが理解しやすく、効率的にコード生成できる構造</li>



<li><strong>将来性</strong>: Meta（旧Facebook）による継続的な開発とサポート</li>
</ul>



<p>Reactを学ぶことで、AIツールを活用した効率的な開発と、手動での細かい調整の両方を身につけることができます。これは、これからの時代の開発者にとって非常に重要なスキルです。</p>



<h2 class="wp-block-heading" id="anc-posts-list">基本編の学習内容（第1回〜第7回）</h2>



<p class="has-text-align-center is-style-balloon_box u-mb-ctrl u-mb-10"><span data-icon="LsLightbulb" data-id="0" style="--the-icon-svg: url(data:image/svg+xml;base64,PHN2ZyBoZWlnaHQ9IjFlbSIgd2lkdGg9IjFlbSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiBhcmlhLWhpZGRlbj0idHJ1ZSIgdmlld0JveD0iMCAwIDQ4IDQ4Ij48cGF0aCBkPSJNMzIgNDYuNUgxNmMtMS4xIDAtMi0uOS0yLTJzLjktMiAyLTJoMTZjMS4xIDAgMiAuOSAyIDJzLS45IDItMiAyek00MS43IDE1LjlDNDEuMyAxMyA0MCAxMC4zIDM4LjIgOCAzNC41IDMuMiAyOSAuOCAyMy4xIDEgMTQgMS40IDYuNSA4LjkgNiAxOGMtLjMgNiAyLjQgMTEuNyA3LjIgMTUuNC41LjQuOC45LjggMS41djEuNmMwIDIuMiAxLjggNCA0IDRoMTJjMi4yIDAgNC0xLjggNC00VjM1YzAtLjYuMy0xLjIuOS0xLjcgNS4zLTQgOC0xMC42IDYuOC0xNy40em0tNy4xIDEuN2gtLjNjLS43IDAtMS4zLS41LTEuNS0xLjItLjctMy4yLTMuMi01LjctNi40LTYuMy0uOC0uMS0xLjQtLjktMS4yLTEuN3MuOS0xLjQgMS43LTEuMmM0LjQuOCA4IDQuMiA4LjkgOC42LjEuOC0uNCAxLjYtMS4yIDEuOHoiPjwvcGF0aD48L3N2Zz4=)" aria-hidden="true" class="swl-inline-icon"> </span> <strong>完成イメージ</strong></p>


<div class="wp-block-image is-style-browser_mac size_xs">
<figure class="aligncenter size-large"><img decoding="async" width="1024" height="655" src="https://kekenta-it-blog.com/wp-content/uploads/2025/07/react_todo_series_06_01-1024x655.jpg" alt="TODOアプリ（基本編）完成イメージ" class="wp-image-15513" srcset="https://kekenta-it-blog.com/wp-content/uploads/2025/07/react_todo_series_06_01-1024x655.jpg 1024w, https://kekenta-it-blog.com/wp-content/uploads/2025/07/react_todo_series_06_01-300x192.jpg 300w, https://kekenta-it-blog.com/wp-content/uploads/2025/07/react_todo_series_06_01-768x491.jpg 768w, https://kekenta-it-blog.com/wp-content/uploads/2025/07/react_todo_series_06_01.jpg 1268w" sizes="(max-width: 1024px) 100vw, 1024px" /><figcaption class="wp-element-caption">TODOアプリ（基本編）</figcaption></figure>
</div>


<p class="has-text-align-center is-style-balloon_box u-mb-ctrl u-mb-10"><span style="--the-icon-svg: url(data:image/svg+xml;base64,PHN2ZyBoZWlnaHQ9IjFlbSIgd2lkdGg9IjFlbSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiBhcmlhLWhpZGRlbj0idHJ1ZSIgdmlld0JveD0iMCAwIDQ4IDQ4Ij48cGF0aCBkPSJNMTAgM2gyOGMxLjEgMCAyIC45IDIgMnYzOS42YzAgLjktMS4xIDEuMy0xLjcuN0wyNCAzMSA5LjcgNDUuM2MtLjYuNi0xLjcuMi0xLjctLjdWNWMwLTEuMS45LTIgMi0yeiI+PC9wYXRoPjwvc3ZnPg==)" data-icon="LsBookmark" data-id="0" aria-hidden="true" class="swl-inline-icon"> </span> <strong>記事リスト</strong></p>



<ul class="swell-block-linkList is-style-button" style="--the-color:var(--color_main)">
<li class="swell-block-linkList__item"><a class="swell-block-linkList__link" href="https://kekenta-it-blog.com/react-todo-app-development-basics/"><svg xmlns="http://www.w3.org/2000/svg" class="swl-svg-arrowCircleRight swell-block-linkList__icon -right" width="1em" height="1em" viewBox="0 0 48 48" role="img" aria-hidden="true" focusable="false"><path d="M24 45C12.4 45 3 35.6 3 24S12.4 3 24 3s21 9.4 21 21-9.4 21-21 21zm0-39C14.1 6 6 14.1 6 24s8.1 18 18 18 18-8.1 18-18S33.9 6 24 6z" /><path d="m34.3 22.9-8.8-8.8c-.6-.6-1.5-.6-2.1 0s-.6 1.5 0 2.1l6.3 6.3H14.8c-.8 0-1.5.7-1.5 1.5s.7 1.5 1.5 1.5h14.8l-6.3 6.3c-.6.6-.6 1.5 0 2.1s1.5.6 2.1 0l8.8-8.8c.7-.6.7-1.6.1-2.2z" /></svg><span class="swell-block-linkList__text">第1回：Reactの基礎と開発環境の準備</span></a></li>



<li class="swell-block-linkList__item"><a class="swell-block-linkList__link" href="https://kekenta-it-blog.com/react-components-jsx-understanding/"><svg xmlns="http://www.w3.org/2000/svg" class="swl-svg-arrowCircleRight swell-block-linkList__icon -right" width="1em" height="1em" viewBox="0 0 48 48" role="img" aria-hidden="true" focusable="false"><path d="M24 45C12.4 45 3 35.6 3 24S12.4 3 24 3s21 9.4 21 21-9.4 21-21 21zm0-39C14.1 6 6 14.1 6 24s8.1 18 18 18 18-8.1 18-18S33.9 6 24 6z" /><path d="m34.3 22.9-8.8-8.8c-.6-.6-1.5-.6-2.1 0s-.6 1.5 0 2.1l6.3 6.3H14.8c-.8 0-1.5.7-1.5 1.5s.7 1.5 1.5 1.5h14.8l-6.3 6.3c-.6.6-.6 1.5 0 2.1s1.5.6 2.1 0l8.8-8.8c.7-.6.7-1.6.1-2.2z" /></svg><span class="swell-block-linkList__text">第2回：コンポーネントとJSXの理解</span></a></li>



<li class="swell-block-linkList__item"><a class="swell-block-linkList__link" href="https://kekenta-it-blog.com/react-state-management-usestate/"><svg xmlns="http://www.w3.org/2000/svg" class="swl-svg-arrowCircleRight swell-block-linkList__icon -right" width="1em" height="1em" viewBox="0 0 48 48" role="img" aria-hidden="true" focusable="false"><path d="M24 45C12.4 45 3 35.6 3 24S12.4 3 24 3s21 9.4 21 21-9.4 21-21 21zm0-39C14.1 6 6 14.1 6 24s8.1 18 18 18 18-8.1 18-18S33.9 6 24 6z" /><path d="m34.3 22.9-8.8-8.8c-.6-.6-1.5-.6-2.1 0s-.6 1.5 0 2.1l6.3 6.3H14.8c-.8 0-1.5.7-1.5 1.5s.7 1.5 1.5 1.5h14.8l-6.3 6.3c-.6.6-.6 1.5 0 2.1s1.5.6 2.1 0l8.8-8.8c.7-.6.7-1.6.1-2.2z" /></svg><span class="swell-block-linkList__text">第3回：状態管理の基礎 &#8211; useState</span></a></li>



<li class="swell-block-linkList__item"><a class="swell-block-linkList__link" href="https://kekenta-it-blog.com/react-event-handling-form-processing/"><svg xmlns="http://www.w3.org/2000/svg" class="swl-svg-arrowCircleRight swell-block-linkList__icon -right" width="1em" height="1em" viewBox="0 0 48 48" role="img" aria-hidden="true" focusable="false"><path d="M24 45C12.4 45 3 35.6 3 24S12.4 3 24 3s21 9.4 21 21-9.4 21-21 21zm0-39C14.1 6 6 14.1 6 24s8.1 18 18 18 18-8.1 18-18S33.9 6 24 6z" /><path d="m34.3 22.9-8.8-8.8c-.6-.6-1.5-.6-2.1 0s-.6 1.5 0 2.1l6.3 6.3H14.8c-.8 0-1.5.7-1.5 1.5s.7 1.5 1.5 1.5h14.8l-6.3 6.3c-.6.6-.6 1.5 0 2.1s1.5.6 2.1 0l8.8-8.8c.7-.6.7-1.6.1-2.2z" /></svg><span class="swell-block-linkList__text">第4回：イベントハンドリングとフォーム処理</span></a></li>



<li class="swell-block-linkList__item"><a class="swell-block-linkList__link" href="https://kekenta-it-blog.com/react-list-display-conditional-rendering/"><svg xmlns="http://www.w3.org/2000/svg" class="swl-svg-arrowCircleRight swell-block-linkList__icon -right" width="1em" height="1em" viewBox="0 0 48 48" role="img" aria-hidden="true" focusable="false"><path d="M24 45C12.4 45 3 35.6 3 24S12.4 3 24 3s21 9.4 21 21-9.4 21-21 21zm0-39C14.1 6 6 14.1 6 24s8.1 18 18 18 18-8.1 18-18S33.9 6 24 6z" /><path d="m34.3 22.9-8.8-8.8c-.6-.6-1.5-.6-2.1 0s-.6 1.5 0 2.1l6.3 6.3H14.8c-.8 0-1.5.7-1.5 1.5s.7 1.5 1.5 1.5h14.8l-6.3 6.3c-.6.6-.6 1.5 0 2.1s1.5.6 2.1 0l8.8-8.8c.7-.6.7-1.6.1-2.2z" /></svg><span class="swell-block-linkList__text">第5回：リスト表示と条件付きレンダリング</span></a></li>



<li class="swell-block-linkList__item"><a class="swell-block-linkList__link" href="https://kekenta-it-blog.com/react-todo-app-edit-delete-crud/"><svg xmlns="http://www.w3.org/2000/svg" class="swl-svg-arrowCircleRight swell-block-linkList__icon -right" width="1em" height="1em" viewBox="0 0 48 48" role="img" aria-hidden="true" focusable="false"><path d="M24 45C12.4 45 3 35.6 3 24S12.4 3 24 3s21 9.4 21 21-9.4 21-21 21zm0-39C14.1 6 6 14.1 6 24s8.1 18 18 18 18-8.1 18-18S33.9 6 24 6z" /><path d="m34.3 22.9-8.8-8.8c-.6-.6-1.5-.6-2.1 0s-.6 1.5 0 2.1l6.3 6.3H14.8c-.8 0-1.5.7-1.5 1.5s.7 1.5 1.5 1.5h14.8l-6.3 6.3c-.6.6-.6 1.5 0 2.1s1.5.6 2.1 0l8.8-8.8c.7-.6.7-1.6.1-2.2z" /></svg><span class="swell-block-linkList__text">第6回：TODOの編集と削除機能</span></a></li>



<li class="swell-block-linkList__item"><a class="swell-block-linkList__link" href="https://kekenta-it-blog.com/react-todo-app-useeffect-localstrage/"><svg xmlns="http://www.w3.org/2000/svg" class="swl-svg-arrowCircleRight swell-block-linkList__icon -right" width="1em" height="1em" viewBox="0 0 48 48" role="img" aria-hidden="true" focusable="false"><path d="M24 45C12.4 45 3 35.6 3 24S12.4 3 24 3s21 9.4 21 21-9.4 21-21 21zm0-39C14.1 6 6 14.1 6 24s8.1 18 18 18 18-8.1 18-18S33.9 6 24 6z" /><path d="m34.3 22.9-8.8-8.8c-.6-.6-1.5-.6-2.1 0s-.6 1.5 0 2.1l6.3 6.3H14.8c-.8 0-1.5.7-1.5 1.5s.7 1.5 1.5 1.5h14.8l-6.3 6.3c-.6.6-.6 1.5 0 2.1s1.5.6 2.1 0l8.8-8.8c.7-.6.7-1.6.1-2.2z" /></svg><span class="swell-block-linkList__text">第7回：useEffectとlocalStorageを使ったデータ永続化</span></a></li>
</ul>



<h3 class="wp-block-heading">第1回：Reactの基礎と開発環境の準備</h3>


<div class="swell-block-postLink">			<div class="p-blogCard -internal" data-type="type2" data-onclick="clickLink">
				<div class="p-blogCard__inner">
					<span class="p-blogCard__caption">シリーズ第1回</span>
					<div class="p-blogCard__thumb c-postThumb"><figure class="c-postThumb__figure"><img decoding="async" src="https://kekenta-it-blog.com/wp-content/uploads/2025/07/eye-catch__react-todo-app-development-basics__15419-300x169.jpg" alt="" class="c-postThumb__img u-obf-cover" width="320" height="180"></figure></div>					<div class="p-blogCard__body">
						<a class="p-blogCard__title" href="https://kekenta-it-blog.com/react-todo-app-development-basics/">【React×TODOアプリ】Reactの基礎と開発環境の準備【基本編：第1回】</a>
											</div>
				</div>
			</div>
		</div>


<p class="is-style-balloon_box u-mb-ctrl u-mb-10"><span style="--the-icon-svg: url(data:image/svg+xml;base64,PHN2ZyBoZWlnaHQ9IjFlbSIgd2lkdGg9IjFlbSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiBhcmlhLWhpZGRlbj0idHJ1ZSIgdmlld0JveD0iMCAwIDQ4IDQ4Ij48cGF0aCBkPSJNMzIgNDYuNUgxNmMtMS4xIDAtMi0uOS0yLTJzLjktMiAyLTJoMTZjMS4xIDAgMiAuOSAyIDJzLS45IDItMiAyek00MS43IDE1LjlDNDEuMyAxMyA0MCAxMC4zIDM4LjIgOCAzNC41IDMuMiAyOSAuOCAyMy4xIDEgMTQgMS40IDYuNSA4LjkgNiAxOGMtLjMgNiAyLjQgMTEuNyA3LjIgMTUuNC41LjQuOC45LjggMS41djEuNmMwIDIuMiAxLjggNCA0IDRoMTJjMi4yIDAgNC0xLjggNC00VjM1YzAtLjYuMy0xLjIuOS0xLjcgNS4zLTQgOC0xMC42IDYuOC0xNy40em0tNy4xIDEuN2gtLjNjLS43IDAtMS4zLS41LTEuNS0xLjItLjctMy4yLTMuMi01LjctNi40LTYuMy0uOC0uMS0xLjQtLjktMS4yLTEuN3MuOS0xLjQgMS43LTEuMmM0LjQuOCA4IDQuMiA4LjkgOC42LjEuOC0uNCAxLjYtMS4yIDEuOHoiPjwvcGF0aD48L3N2Zz4=)" data-icon="LsLightbulb" data-id="0" aria-hidden="true" class="swl-inline-icon"> </span><strong> </strong><strong>学べること</strong></p>



<div class="wp-block-group has-border -border01"><div class="wp-block-group__inner-container is-layout-constrained wp-block-group-is-layout-constrained">
<ul class="wp-block-list is-style-check_list">
<li>Reactの基本概念（仮想DOM、コンポーネントベース開発）</li>



<li>Node.jsとnpmのインストール</li>



<li>Create React Appでのプロジェクト作成</li>



<li>JSXの基本文法</li>



<li>初回コンポーネントの作成</li>
</ul>
</div></div>



<p class="is-style-icon_good">開発環境が整い、基本的なReactアプリが作れるようになります。</p>



<h3 class="wp-block-heading">第2回：コンポーネントとJSXの理解</h3>


<div class="swell-block-postLink">			<div class="p-blogCard -internal" data-type="type2" data-onclick="clickLink">
				<div class="p-blogCard__inner">
					<span class="p-blogCard__caption">シリーズ第2回</span>
					<div class="p-blogCard__thumb c-postThumb"><figure class="c-postThumb__figure"><img decoding="async" src="https://kekenta-it-blog.com/wp-content/uploads/2025/07/eye-catch__react-components-jsx-understanding__15432-300x169.jpg" alt="" class="c-postThumb__img u-obf-cover" width="320" height="180"></figure></div>					<div class="p-blogCard__body">
						<a class="p-blogCard__title" href="https://kekenta-it-blog.com/react-components-jsx-understanding/">【React×TODOアプリ】コンポーネントとJSXの理解【基本編：第2回】</a>
											</div>
				</div>
			</div>
		</div>


<p class="is-style-balloon_box u-mb-ctrl u-mb-10"><span style="--the-icon-svg: url(data:image/svg+xml;base64,PHN2ZyBoZWlnaHQ9IjFlbSIgd2lkdGg9IjFlbSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiBhcmlhLWhpZGRlbj0idHJ1ZSIgdmlld0JveD0iMCAwIDQ4IDQ4Ij48cGF0aCBkPSJNMzIgNDYuNUgxNmMtMS4xIDAtMi0uOS0yLTJzLjktMiAyLTJoMTZjMS4xIDAgMiAuOSAyIDJzLS45IDItMiAyek00MS43IDE1LjlDNDEuMyAxMyA0MCAxMC4zIDM4LjIgOCAzNC41IDMuMiAyOSAuOCAyMy4xIDEgMTQgMS40IDYuNSA4LjkgNiAxOGMtLjMgNiAyLjQgMTEuNyA3LjIgMTUuNC41LjQuOC45LjggMS41djEuNmMwIDIuMiAxLjggNCA0IDRoMTJjMi4yIDAgNC0xLjggNC00VjM1YzAtLjYuMy0xLjIuOS0xLjcgNS4zLTQgOC0xMC42IDYuOC0xNy40em0tNy4xIDEuN2gtLjNjLS43IDAtMS4zLS41LTEuNS0xLjItLjctMy4yLTMuMi01LjctNi40LTYuMy0uOC0uMS0xLjQtLjktMS4yLTEuN3MuOS0xLjQgMS43LTEuMmM0LjQuOCA4IDQuMiA4LjkgOC42LjEuOC0uNCAxLjYtMS4yIDEuOHoiPjwvcGF0aD48L3N2Zz4=)" data-icon="LsLightbulb" data-id="0" aria-hidden="true" class="swl-inline-icon"> </span><strong> </strong><strong>学べること</strong></p>



<div class="wp-block-group has-border -border01"><div class="wp-block-group__inner-container is-layout-constrained wp-block-group-is-layout-constrained">
<ul class="wp-block-list is-style-check_list">
<li>コンポーネントの概念と種類（関数コンポーネント、クラスコンポーネント）</li>



<li>JSXの詳細な文法</li>



<li>Propsの受け渡し</li>



<li>コンポーネントの分割と再利用</li>
</ul>
</div></div>



<p class="is-style-icon_good">コンポーネントベース開発の考え方を理解し、再利用可能なコンポーネントの設計ができるようになります。</p>



<h3 class="wp-block-heading">第3回：状態管理の基礎 &#8211; useState</h3>


<div class="swell-block-postLink">			<div class="p-blogCard -internal" data-type="type2" data-onclick="clickLink">
				<div class="p-blogCard__inner">
					<span class="p-blogCard__caption">シリーズ第3回</span>
					<div class="p-blogCard__thumb c-postThumb"><figure class="c-postThumb__figure"><img decoding="async" src="https://kekenta-it-blog.com/wp-content/uploads/2025/07/eye-catch__react-state-management-usestate__15448-300x169.jpg" alt="" class="c-postThumb__img u-obf-cover" width="320" height="180"></figure></div>					<div class="p-blogCard__body">
						<a class="p-blogCard__title" href="https://kekenta-it-blog.com/react-state-management-usestate/">【React×TODOアプリ】状態管理の基礎 &#8211; useState【基本編：第3回】</a>
											</div>
				</div>
			</div>
		</div>


<p class="is-style-balloon_box u-mb-ctrl u-mb-10"><span style="--the-icon-svg: url(data:image/svg+xml;base64,PHN2ZyBoZWlnaHQ9IjFlbSIgd2lkdGg9IjFlbSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiBhcmlhLWhpZGRlbj0idHJ1ZSIgdmlld0JveD0iMCAwIDQ4IDQ4Ij48cGF0aCBkPSJNMzIgNDYuNUgxNmMtMS4xIDAtMi0uOS0yLTJzLjktMiAyLTJoMTZjMS4xIDAgMiAuOSAyIDJzLS45IDItMiAyek00MS43IDE1LjlDNDEuMyAxMyA0MCAxMC4zIDM4LjIgOCAzNC41IDMuMiAyOSAuOCAyMy4xIDEgMTQgMS40IDYuNSA4LjkgNiAxOGMtLjMgNiAyLjQgMTEuNyA3LjIgMTUuNC41LjQuOC45LjggMS41djEuNmMwIDIuMiAxLjggNCA0IDRoMTJjMi4yIDAgNC0xLjggNC00VjM1YzAtLjYuMy0xLjIuOS0xLjcgNS4zLTQgOC0xMC42IDYuOC0xNy40em0tNy4xIDEuN2gtLjNjLS43IDAtMS4zLS41LTEuNS0xLjItLjctMy4yLTMuMi01LjctNi40LTYuMy0uOC0uMS0xLjQtLjktMS4yLTEuN3MuOS0xLjQgMS43LTEuMmM0LjQuOCA4IDQuMiA4LjkgOC42LjEuOC0uNCAxLjYtMS4yIDEuOHoiPjwvcGF0aD48L3N2Zz4=)" data-icon="LsLightbulb" data-id="0" aria-hidden="true" class="swl-inline-icon"> </span><strong> </strong><strong>学べること</strong></p>



<div class="wp-block-group has-border -border01"><div class="wp-block-group__inner-container is-layout-constrained wp-block-group-is-layout-constrained">
<ul class="wp-block-list is-style-check_list">
<li>useStateフックの基本</li>



<li>状態の更新方法</li>



<li>配列とオブジェクトの状態管理</li>



<li>TODOリストの基本構造作成</li>
</ul>
</div></div>



<p class="is-style-icon_good">Reactでの状態管理の基本を理解し、動的な状態管理ができるTODOアプリを構築できます。</p>



<h3 class="wp-block-heading">第4回：イベントハンドリングとフォーム処理</h3>


<div class="swell-block-postLink">			<div class="p-blogCard -internal" data-type="type2" data-onclick="clickLink">
				<div class="p-blogCard__inner">
					<span class="p-blogCard__caption">シリーズ第4回</span>
					<div class="p-blogCard__thumb c-postThumb"><figure class="c-postThumb__figure"><img decoding="async" src="https://kekenta-it-blog.com/wp-content/uploads/2025/07/eye-catch__react-event-handling-form-processing__15483-300x169.jpg" alt="" class="c-postThumb__img u-obf-cover" width="320" height="180"></figure></div>					<div class="p-blogCard__body">
						<a class="p-blogCard__title" href="https://kekenta-it-blog.com/react-event-handling-form-processing/">【React×TODOアプリ】イベントハンドリングとフォーム処理【基本編：第4回】</a>
											</div>
				</div>
			</div>
		</div>


<p class="is-style-balloon_box u-mb-ctrl u-mb-10"><span style="--the-icon-svg: url(data:image/svg+xml;base64,PHN2ZyBoZWlnaHQ9IjFlbSIgd2lkdGg9IjFlbSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiBhcmlhLWhpZGRlbj0idHJ1ZSIgdmlld0JveD0iMCAwIDQ4IDQ4Ij48cGF0aCBkPSJNMzIgNDYuNUgxNmMtMS4xIDAtMi0uOS0yLTJzLjktMiAyLTJoMTZjMS4xIDAgMiAuOSAyIDJzLS45IDItMiAyek00MS43IDE1LjlDNDEuMyAxMyA0MCAxMC4zIDM4LjIgOCAzNC41IDMuMiAyOSAuOCAyMy4xIDEgMTQgMS40IDYuNSA4LjkgNiAxOGMtLjMgNiAyLjQgMTEuNyA3LjIgMTUuNC41LjQuOC45LjggMS41djEuNmMwIDIuMiAxLjggNCA0IDRoMTJjMi4yIDAgNC0xLjggNC00VjM1YzAtLjYuMy0xLjIuOS0xLjcgNS4zLTQgOC0xMC42IDYuOC0xNy40em0tNy4xIDEuN2gtLjNjLS43IDAtMS4zLS41LTEuNS0xLjItLjctMy4yLTMuMi01LjctNi40LTYuMy0uOC0uMS0xLjQtLjktMS4yLTEuN3MuOS0xLjQgMS43LTEuMmM0LjQuOCA4IDQuMiA4LjkgOC42LjEuOC0uNCAxLjYtMS4yIDEuOHoiPjwvcGF0aD48L3N2Zz4=)" data-icon="LsLightbulb" data-id="0" aria-hidden="true" class="swl-inline-icon"> </span><strong> </strong><strong>学べること</strong></p>



<div class="wp-block-group has-border -border01"><div class="wp-block-group__inner-container is-layout-constrained wp-block-group-is-layout-constrained">
<ul class="wp-block-list is-style-check_list">
<li>イベントハンドラーの書き方</li>



<li>フォームの制御（制御されたコンポーネント）</li>



<li>入力値の検証とバリデーション</li>



<li>エラーハンドリングの基礎</li>
</ul>
</div></div>



<p class="is-style-icon_good">ユーザー入力の処理方法を理解し、適切なフォーム機能を実装できるようになります。</p>



<h3 class="wp-block-heading">第5回：リスト表示と条件付きレンダリング</h3>


<div class="swell-block-postLink">			<div class="p-blogCard -internal" data-type="type2" data-onclick="clickLink">
				<div class="p-blogCard__inner">
					<span class="p-blogCard__caption">シリーズ第5回</span>
					<div class="p-blogCard__thumb c-postThumb"><figure class="c-postThumb__figure"><img decoding="async" src="https://kekenta-it-blog.com/wp-content/uploads/2025/07/eye-catch__react-list-display-conditional-rendering__15497-300x169.jpg" alt="" class="c-postThumb__img u-obf-cover" width="320" height="180"></figure></div>					<div class="p-blogCard__body">
						<a class="p-blogCard__title" href="https://kekenta-it-blog.com/react-list-display-conditional-rendering/">【React×TODOアプリ】リスト表示と条件付きレンダリング【基本編：第5回】</a>
											</div>
				</div>
			</div>
		</div>


<p class="is-style-balloon_box u-mb-ctrl u-mb-10"><span style="--the-icon-svg: url(data:image/svg+xml;base64,PHN2ZyBoZWlnaHQ9IjFlbSIgd2lkdGg9IjFlbSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiBhcmlhLWhpZGRlbj0idHJ1ZSIgdmlld0JveD0iMCAwIDQ4IDQ4Ij48cGF0aCBkPSJNMzIgNDYuNUgxNmMtMS4xIDAtMi0uOS0yLTJzLjktMiAyLTJoMTZjMS4xIDAgMiAuOSAyIDJzLS45IDItMiAyek00MS43IDE1LjlDNDEuMyAxMyA0MCAxMC4zIDM4LjIgOCAzNC41IDMuMiAyOSAuOCAyMy4xIDEgMTQgMS40IDYuNSA4LjkgNiAxOGMtLjMgNiAyLjQgMTEuNyA3LjIgMTUuNC41LjQuOC45LjggMS41djEuNmMwIDIuMiAxLjggNCA0IDRoMTJjMi4yIDAgNC0xLjggNC00VjM1YzAtLjYuMy0xLjIuOS0xLjcgNS4zLTQgOC0xMC42IDYuOC0xNy40em0tNy4xIDEuN2gtLjNjLS43IDAtMS4zLS41LTEuNS0xLjItLjctMy4yLTMuMi01LjctNi40LTYuMy0uOC0uMS0xLjQtLjktMS4yLTEuN3MuOS0xLjQgMS43LTEuMmM0LjQuOCA4IDQuMiA4LjkgOC42LjEuOC0uNCAxLjYtMS4yIDEuOHoiPjwvcGF0aD48L3N2Zz4=)" data-icon="LsLightbulb" data-id="0" aria-hidden="true" class="swl-inline-icon"> </span><strong> </strong><strong>学べること</strong></p>



<div class="wp-block-group has-border -border01"><div class="wp-block-group__inner-container is-layout-constrained wp-block-group-is-layout-constrained">
<ul class="wp-block-list is-style-check_list">
<li>map関数を使ったリスト表示</li>



<li>keyプロパティの重要性</li>



<li>条件付きレンダリング（&amp;&amp;演算子、三項演算子）</li>



<li>フィルタリング機能の実装</li>
</ul>
</div></div>



<p class="is-style-icon_good">動的なリスト表示の実装方法を理解し、条件に応じたUI制御ができるようになります。</p>



<h3 class="wp-block-heading">第6回：TODOの編集と削除機能</h3>


<div class="swell-block-postLink">			<div class="p-blogCard -internal" data-type="type2" data-onclick="clickLink">
				<div class="p-blogCard__inner">
					<span class="p-blogCard__caption">シリーズ第6回</span>
					<div class="p-blogCard__thumb c-postThumb"><figure class="c-postThumb__figure"><img decoding="async" src="https://kekenta-it-blog.com/wp-content/uploads/2025/07/eye-catch__react-todo-app-edit-delete-crud__15510-300x169.jpg" alt="" class="c-postThumb__img u-obf-cover" width="320" height="180"></figure></div>					<div class="p-blogCard__body">
						<a class="p-blogCard__title" href="https://kekenta-it-blog.com/react-todo-app-edit-delete-crud/">【React×TODOアプリ】編集・削除機能の実装【基本編：第6回】</a>
											</div>
				</div>
			</div>
		</div>


<p class="is-style-balloon_box u-mb-ctrl u-mb-10"><span style="--the-icon-svg: url(data:image/svg+xml;base64,PHN2ZyBoZWlnaHQ9IjFlbSIgd2lkdGg9IjFlbSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiBhcmlhLWhpZGRlbj0idHJ1ZSIgdmlld0JveD0iMCAwIDQ4IDQ4Ij48cGF0aCBkPSJNMzIgNDYuNUgxNmMtMS4xIDAtMi0uOS0yLTJzLjktMiAyLTJoMTZjMS4xIDAgMiAuOSAyIDJzLS45IDItMiAyek00MS43IDE1LjlDNDEuMyAxMyA0MCAxMC4zIDM4LjIgOCAzNC41IDMuMiAyOSAuOCAyMy4xIDEgMTQgMS40IDYuNSA4LjkgNiAxOGMtLjMgNiAyLjQgMTEuNyA3LjIgMTUuNC41LjQuOC45LjggMS41djEuNmMwIDIuMiAxLjggNCA0IDRoMTJjMi4yIDAgNC0xLjggNC00VjM1YzAtLjYuMy0xLjIuOS0xLjcgNS4zLTQgOC0xMC42IDYuOC0xNy40em0tNy4xIDEuN2gtLjNjLS43IDAtMS4zLS41LTEuNS0xLjItLjctMy4yLTMuMi01LjctNi40LTYuMy0uOC0uMS0xLjQtLjktMS4yLTEuN3MuOS0xLjQgMS43LTEuMmM0LjQuOCA4IDQuMiA4LjkgOC42LjEuOC0uNCAxLjYtMS4yIDEuOHoiPjwvcGF0aD48L3N2Zz4=)" data-icon="LsLightbulb" data-id="0" aria-hidden="true" class="swl-inline-icon"> </span><strong> </strong><strong>学べること</strong></p>



<div class="wp-block-group has-border -border01"><div class="wp-block-group__inner-container is-layout-constrained wp-block-group-is-layout-constrained">
<ul class="wp-block-list is-style-check_list">
<li>配列の操作（filter、map、findIndex）</li>



<li>イベントの伝播と停止</li>



<li>編集モードの切り替え</li>



<li>キーボードショートカットの実装</li>
</ul>
</div></div>



<p class="is-style-icon_good">完全なCRUD操作（Create、Read、Update、Delete）ができるTODOアプリを完成させられます。</p>



<h3 class="wp-block-heading">第7回：useEffectとlocalStorageを使ったデータ永続化</h3>


<div class="swell-block-postLink">			<div class="p-blogCard -internal" data-type="type2" data-onclick="clickLink">
				<div class="p-blogCard__inner">
					<span class="p-blogCard__caption">シリーズ第7回</span>
					<div class="p-blogCard__thumb c-postThumb"><figure class="c-postThumb__figure"><img decoding="async" src="https://kekenta-it-blog.com/wp-content/uploads/2025/07/eye-catch__react-todo-app-useeffect-localstrage__15530-300x169.jpg" alt="" class="c-postThumb__img u-obf-cover" width="320" height="180"></figure></div>					<div class="p-blogCard__body">
						<a class="p-blogCard__title" href="https://kekenta-it-blog.com/react-todo-app-useeffect-localstrage/">【React×TODOアプリ】useEffectと副作用・ローカルストレージ【基本編：第7回】</a>
											</div>
				</div>
			</div>
		</div>


<p class="is-style-balloon_box u-mb-ctrl u-mb-10"><span style="--the-icon-svg: url(data:image/svg+xml;base64,PHN2ZyBoZWlnaHQ9IjFlbSIgd2lkdGg9IjFlbSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiBhcmlhLWhpZGRlbj0idHJ1ZSIgdmlld0JveD0iMCAwIDQ4IDQ4Ij48cGF0aCBkPSJNMzIgNDYuNUgxNmMtMS4xIDAtMi0uOS0yLTJzLjktMiAyLTJoMTZjMS4xIDAgMiAuOSAyIDJzLS45IDItMiAyek00MS43IDE1LjlDNDEuMyAxMyA0MCAxMC4zIDM4LjIgOCAzNC41IDMuMiAyOSAuOCAyMy4xIDEgMTQgMS40IDYuNSA4LjkgNiAxOGMtLjMgNiAyLjQgMTEuNyA3LjIgMTUuNC41LjQuOC45LjggMS41djEuNmMwIDIuMiAxLjggNCA0IDRoMTJjMi4yIDAgNC0xLjggNC00VjM1YzAtLjYuMy0xLjIuOS0xLjcgNS4zLTQgOC0xMC42IDYuOC0xNy40em0tNy4xIDEuN2gtLjNjLS43IDAtMS4zLS41LTEuNS0xLjItLjctMy4yLTMuMi01LjctNi40LTYuMy0uOC0uMS0xLjQtLjktMS4yLTEuN3MuOS0xLjQgMS43LTEuMmM0LjQuOCA4IDQuMiA4LjkgOC42LjEuOC0uNCAxLjYtMS4yIDEuOHoiPjwvcGF0aD48L3N2Zz4=)" data-icon="LsLightbulb" data-id="0" aria-hidden="true" class="swl-inline-icon"> </span><strong> </strong><strong>学べること</strong></p>



<div class="wp-block-group has-border -border01"><div class="wp-block-group__inner-container is-layout-constrained wp-block-group-is-layout-constrained">
<ul class="wp-block-list is-style-check_list">
<li>useEffectフックの基本</li>



<li>依存配列の理解</li>



<li>localStorageを使ったデータ永続化</li>
</ul>
</div></div>



<p class="is-style-icon_good">副作用の適切な管理方法を理解し、ブラウザでのデータ永続化機能を実装できるようになります。</p>



<h2 class="wp-block-heading">発展編の学習内容（第1回〜第5回）</h2>



<p class="is-style-icon_info"><strong>※発展編の記事はこれから順次執筆していく予定です。</strong></p>



<h3 class="wp-block-heading">第1回：スタイリングとUI/UX改善（予定）</h3>



<p class="is-style-icon_pen">鋭意制作中です。</p>



<p class="is-style-balloon_box u-mb-ctrl u-mb-10"><span style="--the-icon-svg: url(data:image/svg+xml;base64,PHN2ZyBoZWlnaHQ9IjFlbSIgd2lkdGg9IjFlbSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiBhcmlhLWhpZGRlbj0idHJ1ZSIgdmlld0JveD0iMCAwIDQ4IDQ4Ij48cGF0aCBkPSJNMzIgNDYuNUgxNmMtMS4xIDAtMi0uOS0yLTJzLjktMiAyLTJoMTZjMS4xIDAgMiAuOSAyIDJzLS45IDItMiAyek00MS43IDE1LjlDNDEuMyAxMyA0MCAxMC4zIDM4LjIgOCAzNC41IDMuMiAyOSAuOCAyMy4xIDEgMTQgMS40IDYuNSA4LjkgNiAxOGMtLjMgNiAyLjQgMTEuNyA3LjIgMTUuNC41LjQuOC45LjggMS41djEuNmMwIDIuMiAxLjggNCA0IDRoMTJjMi4yIDAgNC0xLjggNC00VjM1YzAtLjYuMy0xLjIuOS0xLjcgNS4zLTQgOC0xMC42IDYuOC0xNy40em0tNy4xIDEuN2gtLjNjLS43IDAtMS4zLS41LTEuNS0xLjItLjctMy4yLTMuMi01LjctNi40LTYuMy0uOC0uMS0xLjQtLjktMS4yLTEuN3MuOS0xLjQgMS43LTEuMmM0LjQuOCA4IDQuMiA4LjkgOC42LjEuOC0uNCAxLjYtMS4yIDEuOHoiPjwvcGF0aD48L3N2Zz4=)" data-icon="LsLightbulb" data-id="0" aria-hidden="true" class="swl-inline-icon"> </span><strong> </strong><strong>学べること</strong></p>



<div class="wp-block-group has-border -border01"><div class="wp-block-group__inner-container is-layout-constrained wp-block-group-is-layout-constrained">
<ul class="wp-block-list is-style-check_list">
<li>CSS-in-JS（styled-components）の基礎</li>



<li>CSSモジュールの使用</li>



<li>レスポンシブデザインの実装</li>



<li>アニメーションの追加</li>
</ul>
</div></div>



<p class="is-style-icon_good">モダンなスタイリング手法を理解し、美しく使いやすいUIを設計できるようになります。</p>



<h3 class="wp-block-heading">第2回：カスタムフックとロジックの分離（予定）</h3>



<p class="is-style-icon_pen">鋭意制作中です。</p>



<p class="is-style-balloon_box u-mb-ctrl u-mb-10"><span style="--the-icon-svg: url(data:image/svg+xml;base64,PHN2ZyBoZWlnaHQ9IjFlbSIgd2lkdGg9IjFlbSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiBhcmlhLWhpZGRlbj0idHJ1ZSIgdmlld0JveD0iMCAwIDQ4IDQ4Ij48cGF0aCBkPSJNMzIgNDYuNUgxNmMtMS4xIDAtMi0uOS0yLTJzLjktMiAyLTJoMTZjMS4xIDAgMiAuOSAyIDJzLS45IDItMiAyek00MS43IDE1LjlDNDEuMyAxMyA0MCAxMC4zIDM4LjIgOCAzNC41IDMuMiAyOSAuOCAyMy4xIDEgMTQgMS40IDYuNSA4LjkgNiAxOGMtLjMgNiAyLjQgMTEuNyA3LjIgMTUuNC41LjQuOC45LjggMS41djEuNmMwIDIuMiAxLjggNCA0IDRoMTJjMi4yIDAgNC0xLjggNC00VjM1YzAtLjYuMy0xLjIuOS0xLjcgNS4zLTQgOC0xMC42IDYuOC0xNy40em0tNy4xIDEuN2gtLjNjLS43IDAtMS4zLS41LTEuNS0xLjItLjctMy4yLTMuMi01LjctNi40LTYuMy0uOC0uMS0xLjQtLjktMS4yLTEuN3MuOS0xLjQgMS43LTEuMmM0LjQuOCA4IDQuMiA4LjkgOC42LjEuOC0uNCAxLjYtMS4yIDEuOHoiPjwvcGF0aD48L3N2Zz4=)" data-icon="LsLightbulb" data-id="0" aria-hidden="true" class="swl-inline-icon"> </span><strong> </strong><strong>学べること</strong></p>



<div class="wp-block-group has-border -border01"><div class="wp-block-group__inner-container is-layout-constrained wp-block-group-is-layout-constrained">
<ul class="wp-block-list is-style-check_list">
<li>カスタムフックの作成</li>



<li>ロジックとUIの分離</li>



<li>useReducerの基礎</li>



<li>エラーハンドリングの改善</li>
</ul>
</div></div>



<p class="is-style-icon_good">コードの再利用性と保守性を向上させる方法を理解し、より複雑な状態管理ができるようになります。</p>



<h3 class="wp-block-heading">第3回：コンテキストAPIとグローバル状態管理（予定）</h3>



<p class="is-style-icon_pen">鋭意制作中です。</p>



<p class="is-style-balloon_box u-mb-ctrl u-mb-10"><span style="--the-icon-svg: url(data:image/svg+xml;base64,PHN2ZyBoZWlnaHQ9IjFlbSIgd2lkdGg9IjFlbSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiBhcmlhLWhpZGRlbj0idHJ1ZSIgdmlld0JveD0iMCAwIDQ4IDQ4Ij48cGF0aCBkPSJNMzIgNDYuNUgxNmMtMS4xIDAtMi0uOS0yLTJzLjktMiAyLTJoMTZjMS4xIDAgMiAuOSAyIDJzLS45IDItMiAyek00MS43IDE1LjlDNDEuMyAxMyA0MCAxMC4zIDM4LjIgOCAzNC41IDMuMiAyOSAuOCAyMy4xIDEgMTQgMS40IDYuNSA4LjkgNiAxOGMtLjMgNiAyLjQgMTEuNyA3LjIgMTUuNC41LjQuOC45LjggMS41djEuNmMwIDIuMiAxLjggNCA0IDRoMTJjMi4yIDAgNC0xLjggNC00VjM1YzAtLjYuMy0xLjIuOS0xLjcgNS4zLTQgOC0xMC42IDYuOC0xNy40em0tNy4xIDEuN2gtLjNjLS43IDAtMS4zLS41LTEuNS0xLjItLjctMy4yLTMuMi01LjctNi40LTYuMy0uOC0uMS0xLjQtLjktMS4yLTEuN3MuOS0xLjQgMS43LTEuMmM0LjQuOCA4IDQuMiA4LjkgOC42LjEuOC0uNCAxLjYtMS4yIDEuOHoiPjwvcGF0aD48L3N2Zz4=)" data-icon="LsLightbulb" data-id="0" aria-hidden="true" class="swl-inline-icon"> </span><strong> </strong><strong>学べること</strong></p>



<div class="wp-block-group has-border -border01"><div class="wp-block-group__inner-container is-layout-constrained wp-block-group-is-layout-constrained">
<ul class="wp-block-list is-style-check_list">
<li>Context APIの基本</li>



<li>ProviderとConsumerの使い方</li>



<li>グローバル状態の設計</li>



<li>パフォーマンスの最適化</li>
</ul>
</div></div>



<p class="is-style-icon_good">大規模アプリケーションでの状態管理方法を理解し、コンポーネント間のデータ共有ができるようになります。</p>



<h3 class="wp-block-heading">第4回：API連携の基礎（予定）</h3>



<p class="is-style-icon_pen">鋭意制作中です。</p>



<p class="is-style-balloon_box u-mb-ctrl u-mb-10"><span style="--the-icon-svg: url(data:image/svg+xml;base64,PHN2ZyBoZWlnaHQ9IjFlbSIgd2lkdGg9IjFlbSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiBhcmlhLWhpZGRlbj0idHJ1ZSIgdmlld0JveD0iMCAwIDQ4IDQ4Ij48cGF0aCBkPSJNMzIgNDYuNUgxNmMtMS4xIDAtMi0uOS0yLTJzLjktMiAyLTJoMTZjMS4xIDAgMiAuOSAyIDJzLS45IDItMiAyek00MS43IDE1LjlDNDEuMyAxMyA0MCAxMC4zIDM4LjIgOCAzNC41IDMuMiAyOSAuOCAyMy4xIDEgMTQgMS40IDYuNSA4LjkgNiAxOGMtLjMgNiAyLjQgMTEuNyA3LjIgMTUuNC41LjQuOC45LjggMS41djEuNmMwIDIuMiAxLjggNCA0IDRoMTJjMi4yIDAgNC0xLjggNC00VjM1YzAtLjYuMy0xLjIuOS0xLjcgNS4zLTQgOC0xMC42IDYuOC0xNy40em0tNy4xIDEuN2gtLjNjLS43IDAtMS4zLS41LTEuNS0xLjItLjctMy4yLTMuMi01LjctNi40LTYuMy0uOC0uMS0xLjQtLjktMS4yLTEuN3MuOS0xLjQgMS43LTEuMmM0LjQuOCA4IDQuMiA4LjkgOC42LjEuOC0uNCAxLjYtMS4yIDEuOHoiPjwvcGF0aD48L3N2Zz4=)" data-icon="LsLightbulb" data-id="0" aria-hidden="true" class="swl-inline-icon"> </span><strong> </strong><strong>学べること</strong></p>



<div class="wp-block-group has-border -border01"><div class="wp-block-group__inner-container is-layout-constrained wp-block-group-is-layout-constrained">
<ul class="wp-block-list is-style-check_list">
<li>fetch APIの基本</li>



<li>async/awaitの使い方</li>



<li>エラーハンドリング</li>



<li>ローディング状態の管理</li>
</ul>
</div></div>



<p class="is-style-icon_good">外部APIとの連携方法を理解し、非同期処理の適切な実装ができるようになります。</p>



<h3 class="wp-block-heading">第5回：データベース連携とデプロイ（予定）</h3>



<p class="is-style-icon_pen">鋭意制作中です。</p>



<p class="is-style-balloon_box u-mb-ctrl u-mb-10"><span style="--the-icon-svg: url(data:image/svg+xml;base64,PHN2ZyBoZWlnaHQ9IjFlbSIgd2lkdGg9IjFlbSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiBhcmlhLWhpZGRlbj0idHJ1ZSIgdmlld0JveD0iMCAwIDQ4IDQ4Ij48cGF0aCBkPSJNMzIgNDYuNUgxNmMtMS4xIDAtMi0uOS0yLTJzLjktMiAyLTJoMTZjMS4xIDAgMiAuOSAyIDJzLS45IDItMiAyek00MS43IDE1LjlDNDEuMyAxMyA0MCAxMC4zIDM4LjIgOCAzNC41IDMuMiAyOSAuOCAyMy4xIDEgMTQgMS40IDYuNSA4LjkgNiAxOGMtLjMgNiAyLjQgMTEuNyA3LjIgMTUuNC41LjQuOC45LjggMS41djEuNmMwIDIuMiAxLjggNCA0IDRoMTJjMi4yIDAgNC0xLjggNC00VjM1YzAtLjYuMy0xLjIuOS0xLjcgNS4zLTQgOC0xMC42IDYuOC0xNy40em0tNy4xIDEuN2gtLjNjLS43IDAtMS4zLS41LTEuNS0xLjItLjctMy4yLTMuMi01LjctNi40LTYuMy0uOC0uMS0xLjQtLjktMS4yLTEuN3MuOS0xLjQgMS43LTEuMmM0LjQuOCA4IDQuMiA4LjkgOC42LjEuOC0uNCAxLjYtMS4yIDEuOHoiPjwvcGF0aD48L3N2Zz4=)" data-icon="LsLightbulb" data-id="0" aria-hidden="true" class="swl-inline-icon"> </span><strong> </strong><strong>学べること</strong></p>



<div class="wp-block-group has-border -border01"><div class="wp-block-group__inner-container is-layout-constrained wp-block-group-is-layout-constrained">
<ul class="wp-block-list is-style-check_list">
<li>バックエンドAPIとの連携</li>



<li>データベース（SQLite/PostgreSQL）の設定</li>



<li>環境変数の管理</li>



<li>アプリケーションのデプロイ（Vercel/Netlify）</li>
</ul>
</div></div>



<p class="is-style-icon_good">フルスタックアプリケーションの開発フローを理解し、本格的なアプリケーションのデプロイ方法を学べます。</p>



<h2 class="wp-block-heading">完成するTODOアプリの機能一覧</h2>



<p class="is-style-bg_stripe">シリーズを完了すると、以下の機能を持つ本格的なTODOアプリが完成します。</p>



<h3 class="wp-block-heading">基本機能</h3>



<ul class="wp-block-list is-style-good_list">
<li>基本的なCRUD操作（作成・読み取り・更新・削除）</li>



<li>完了/未完了の切り替え</li>



<li>優先度設定とバッジ表示</li>



<li>フィルタリング機能（すべて・未完了・完了）</li>



<li>データの永続化（localStorage）</li>
</ul>



<h3 class="wp-block-heading">発展機能</h3>



<ul class="wp-block-list is-style-good_list">
<li>レスポンシブデザイン</li>



<li>ダークモード対応</li>



<li>検索機能</li>



<li>統計表示</li>



<li>エラーハンドリング</li>



<li>ローディング状態の管理</li>
</ul>



<h2 class="wp-block-heading">学習のポイントとコツ</h2>



<h3 class="wp-block-heading">段階的な学習</h3>



<p>基本から応用へ、無理なくステップアップしていくことが重要です。各回の内容をしっかり理解してから次に進みましょう。</p>



<h3 class="wp-block-heading">実践的なアプローチ</h3>



<p>理論だけでなく、実際に手を動かして学んでいくことで、より深い理解が得られます。コードを書いて、動作確認をしながら進めましょう。</p>



<h2 class="wp-block-heading">まとめ</h2>



<p class="is-style-icon_good">このシリーズを通じて、Reactの基礎から実践的なアプリケーション開発まで、段階的に学習していくことができます。</p>



<h3 class="wp-block-heading">身につくスキル</h3>



<ul class="wp-block-list is-style-good_list">
<li>Reactの基本概念と開発手法</li>



<li>コンポーネントベース開発の実践</li>



<li>状態管理の適切な選択と実装</li>



<li>ユーザビリティを考慮したUI設計</li>



<li>フルスタックアプリケーション開発</li>
</ul>



<h3 class="wp-block-heading">継続的な学習の重要性</h3>



<p>技術は日々進歩しています。このシリーズで基礎を固めた後も、新しい技術やベストプラクティスを学び続けることが重要です。</p>



<h3 class="wp-block-heading">読者へのメッセージ</h3>



<p>Reactの学習は、最初は難しく感じるかもしれませんが、段階的に進めていくことで必ず身につきます。基本編から始めて、一つずつ確実に理解していきましょう。発展編の記事も順次公開していきますので、お楽しみに！</p>



<p><strong>基本編の記事は既に公開済みですので、ぜひ<a href="https://kekenta-it-blog.com/react-todo-app-development-basics/" data-type="post" data-id="15419">第1回</a>から順番に学習を始めてください。</strong></p>



<h2 class="wp-block-heading">今こそReactを学ぶ価値がある</h2>



<p>生成AI時代において、Reactの価値はさらに高まっていると言えます。AIツールがフロントエンドコードを生成する際のReactを採用されていることからも、その重要性が証明されています。</p>



<p>僕自身、ここ数か月の間に様々な生成AIやAIエージェントに触れてきて、その中でフロントエンド言語の多くがReactで出力されるケースを目の当たりにしてきました。</p>



<p>生成AIが出力したソースコードを訳も分からず扱うことと、その内容をしっかり理解したうえでソフトウェアへ組み込むことの間には大きな隔たりがあります。だからこそ、これまでReactを学んだことがないという方も、最低限の基本を知るだけでも周囲の方との大きな差になると考えています。</p>


<div class="swell-block-balloon"><div class="c-balloon -bln-left" data-col="gray"><div class="c-balloon__icon -circle"><img decoding="async" src="data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==" data-src="https://kekenta-it-blog.com/wp-content/uploads/2023/11/kekenta-icon-150x150.jpg" alt="" class="lazyload c-balloon__iconImg" width="80px" height="80px"><noscript><img decoding="async" src="https://kekenta-it-blog.com/wp-content/uploads/2023/11/kekenta-icon-150x150.jpg" alt="" class="c-balloon__iconImg" width="80px" height="80px"></noscript><span class="c-balloon__iconName">ケケンタ</span></div><div class="c-balloon__body -speaking -border-on"><div class="c-balloon__text">
<p>この記事でご紹介したTODOアプリ開発シリーズでは、Reactの基本的な解説を交えながら実際にTODOアプリ開発を進めることができます。React初心者の方でも安心して取り組むことができるので、これを機にぜひReactの学習に挑戦してみてください！</p>
<span class="c-balloon__shapes"><span class="c-balloon__before"></span><span class="c-balloon__after"></span></span></div></div></div></div>


<p>気になる第1回目はこちらからご覧いただけます。</p>


<div class="swell-block-postLink">			<div class="p-blogCard -internal" data-type="type2" data-onclick="clickLink">
				<div class="p-blogCard__inner">
					<span class="p-blogCard__caption">シリーズ第1回</span>
					<div class="p-blogCard__thumb c-postThumb"><figure class="c-postThumb__figure"><img decoding="async" src="https://kekenta-it-blog.com/wp-content/uploads/2025/07/eye-catch__react-todo-app-development-basics__15419-300x169.jpg" alt="" class="c-postThumb__img u-obf-cover" width="320" height="180"></figure></div>					<div class="p-blogCard__body">
						<a class="p-blogCard__title" href="https://kekenta-it-blog.com/react-todo-app-development-basics/">【React×TODOアプリ】Reactの基礎と開発環境の準備【基本編：第1回】</a>
						<span class="p-blogCard__excerpt">Reactで作るTODOアプリ開発シリーズ第１回 このシリーズでは、Reactの基礎から実践的なTODOアプリの開発まで、段階的に学習していきます。最終的には、基本編～発展編を&#8230;</span>					</div>
				</div>
			</div>
		</div>


<p>それでは、最後までご覧いただきありがとうございました！</p>


<div class="p-blogParts post_content" data-partsID="15579">
<hr class="wp-block-separator has-alpha-channel-opacity"/>



<p class="is-style-balloon_box"><span style="--the-icon-svg: url(data:image/svg+xml;base64,PHN2ZyBoZWlnaHQ9IjFlbSIgd2lkdGg9IjFlbSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiBhcmlhLWhpZGRlbj0idHJ1ZSIgdmlld0JveD0iMCAwIDQ4IDQ4Ij48cGF0aCBkPSJNMTEuNyAxLjQgNi44IDVjLS41LjQtLjggMS0uOCAxLjZ2MjguN2MwIC44LjUgMS41IDEuMiAxLjhsMjQgMTAuM2MxLjMuNiAyLjgtLjQgMi44LTEuOFYxOWMwLS44LS41LTEuNS0xLjItMS44TDEwLjIgNy41bDIuOS0yLjJjLjktLjYgMi0uOCAzLS40bDIwLjYgOC44Yy43LjMgMS4yIDEgMS4yIDEuOFY0Mi45YzAgLjkgMSAxLjMgMS43LjhsMS43LTEuNWMuNC0uNC43LS45LjctMS41VjEzYzAtLjgtLjUtMS41LTEuMi0xLjhMMTYuNy44Yy0xLjctLjctMy42LS41LTUgLjZ6Ij48L3BhdGg+PC9zdmc+)" data-icon="LsBook" data-id="0" aria-hidden="true" class="swl-inline-icon">  </span> <strong>僕が実際にReact学習に使用した書籍です</strong></p>


<div id="rinkerid15577" class="yyi-rinker-contents  yyi-rinker-postid-15577 yyi-rinker-img-m yyi-rinker-catid-256 ">
	<div class="yyi-rinker-box">
		<div class="yyi-rinker-image">
							<a href="https://www.amazon.co.jp/dp/B09BV2HGN3?tag=kekenta03am0b-22&#038;linkCode=ogi&#038;th=1&#038;psc=1" rel="nofollow" class="yyi-rinker-tracking"  data-click-tracking="amazon_img 15577 モダンJavaScriptの基本から始める　React実践の教科書　（最新ReactHooks対応）" data-vars-click-id="amazon_img 15577 モダンJavaScriptの基本から始める　React実践の教科書　（最新ReactHooks対応）"><img decoding="async" src="https://m.media-amazon.com/images/I/51Y0-P+m94L._SL160_.jpg"  width="112" height="160" class="yyi-rinker-main-img" style="border: none;"></a>					</div>
		<div class="yyi-rinker-info">
			<div class="yyi-rinker-title">
									<a href="https://www.amazon.co.jp/dp/B09BV2HGN3?tag=kekenta03am0b-22&#038;linkCode=ogi&#038;th=1&#038;psc=1" rel="nofollow" class="yyi-rinker-tracking" data-click-tracking="amazon_title 15577 モダンJavaScriptの基本から始める　React実践の教科書　（最新ReactHooks対応）" data-vars-amp-click-id="amazon_title 15577 モダンJavaScriptの基本から始める　React実践の教科書　（最新ReactHooks対応）" >モダンJavaScriptの基本から始める　React実践の教科書　（最新ReactHooks対応）</a>							</div>
			<div class="yyi-rinker-detail">
							<div class="credit-box">created by&nbsp;<a href="https://oyakosodate.com/rinker/" rel="nofollow noopener" target="_blank" >Rinker</a></div>
										<div class="price-box">
							</div>
						</div>
						<ul class="yyi-rinker-links">
																	<li class="amazonkindlelink">
						<a href="https://www.amazon.co.jp/dp/B09BV2HGN3?tag=kekenta03am0b-22&amp;linkCode=ogi&amp;th=1&amp;psc=1" rel="nofollow" class="yyi-rinker-link yyi-rinker-tracking"  data-click-tracking="amazon_kindle 15577 モダンJavaScriptの基本から始める　React実践の教科書　（最新ReactHooks対応）"  data-vars-amp-click-id="amazon_kindle 15577 モダンJavaScriptの基本から始める　React実践の教科書　（最新ReactHooks対応）">Kindle</a>					</li>
								                    <li class="amazonlink">
						<a href="https://www.amazon.co.jp/dp/B09BV2HGN3?tag=kekenta03am0b-22&amp;linkCode=ogi&amp;th=1&amp;psc=1" rel="nofollow" class="yyi-rinker-link yyi-rinker-tracking"  data-click-tracking="amazon 15577 モダンJavaScriptの基本から始める　React実践の教科書　（最新ReactHooks対応）"  data-vars-amp-click-id="amazon 15577 モダンJavaScriptの基本から始める　React実践の教科書　（最新ReactHooks対応）">Amazon</a>					</li>
													<li class="rakutenlink">
						<a href="https://hb.afl.rakuten.co.jp/hgc/3ace225e.aaf54072.3ace225f.2cf27f19/Rinker_o_20250722203529?pc=https%3A%2F%2Fsearch.rakuten.co.jp%2Fsearch%2Fmall%2F%25E3%2583%25A2%25E3%2583%2580%25E3%2583%25B3JavaScript%25E3%2581%25AE%25E5%259F%25BA%25E6%259C%25AC%25E3%2581%258B%25E3%2582%2589%25E5%25A7%258B%25E3%2582%2581%25E3%2582%258B%25E3%2580%2580React%25E5%25AE%259F%25E8%25B7%25B5%25E3%2581%25AE%25E6%2595%2599%25E7%25A7%2591%25E6%259B%25B8%25E3%2580%2580%25EF%25BC%2588%25E6%259C%2580%25E6%2596%25B0ReactHooks%25E5%25AF%25BE%25E5%25BF%259C%25EF%25BC%2589%2F%3Ff%3D1%26grp%3Dproduct&amp;m=https%3A%2F%2Fsearch.rakuten.co.jp%2Fsearch%2Fmall%2F%25E3%2583%25A2%25E3%2583%2580%25E3%2583%25B3JavaScript%25E3%2581%25AE%25E5%259F%25BA%25E6%259C%25AC%25E3%2581%258B%25E3%2582%2589%25E5%25A7%258B%25E3%2582%2581%25E3%2582%258B%25E3%2580%2580React%25E5%25AE%259F%25E8%25B7%25B5%25E3%2581%25AE%25E6%2595%2599%25E7%25A7%2591%25E6%259B%25B8%25E3%2580%2580%25EF%25BC%2588%25E6%259C%2580%25E6%2596%25B0ReactHooks%25E5%25AF%25BE%25E5%25BF%259C%25EF%25BC%2589%2F%3Ff%3D1%26grp%3Dproduct" rel="nofollow" class="yyi-rinker-link yyi-rinker-tracking"  data-click-tracking="rakuten 15577 モダンJavaScriptの基本から始める　React実践の教科書　（最新ReactHooks対応）"  data-vars-amp-click-id="rakuten 15577 モダンJavaScriptの基本から始める　React実践の教科書　（最新ReactHooks対応）">楽天市場</a>					</li>
								                											</ul>
					</div>
	</div>
</div>
</div>
]]></content:encoded>
					
					<wfw:commentRss>https://kekenta-it-blog.com/react-todo-app-series-complete-guide-summary/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>【React×TODOアプリ】useEffectと副作用・ローカルストレージ【基本編：第7回】</title>
		<link>https://kekenta-it-blog.com/react-todo-app-useeffect-localstrage/</link>
					<comments>https://kekenta-it-blog.com/react-todo-app-useeffect-localstrage/#respond</comments>
		
		<dc:creator><![CDATA[ケケンタ]]></dc:creator>
		<pubDate>Tue, 22 Jul 2025 02:09:10 +0000</pubDate>
				<category><![CDATA[React]]></category>
		<category><![CDATA[Javascript]]></category>
		<category><![CDATA[TODOアプリ]]></category>
		<category><![CDATA[開発シリーズ]]></category>
		<guid isPermaLink="false">https://kekenta-it-blog.com/?p=15530</guid>

					<description><![CDATA[<p><img src="https://kekenta-it-blog.com/wp-content/uploads/2025/07/eye-catch__react-todo-app-useeffect-localstrage__15530-1024x576.jpg" class="webfeedsFeaturedVisual" /></p>Reactで作るTODOアプリ開発シリーズ第７回（基本編 最終回） いよいよ基本編の最終回となるこの記事では、 ReactのuseEffectフックを使った副作用処理とローカルストレージによるデータ永続化 について学びま [&#8230;]]]></description>
										<content:encoded><![CDATA[<p><img src="https://kekenta-it-blog.com/wp-content/uploads/2025/07/eye-catch__react-todo-app-useeffect-localstrage__15530-1024x576.jpg" class="webfeedsFeaturedVisual" /></p>
<p><strong>Reactで作るTODOアプリ開発シリーズ第７回（基本編 最終回）</strong></p>



<p>いよいよ基本編の最終回となるこの記事では、</p>



<p class="has-text-align-center is-style-big_kakko_box">Reactの<strong>useEffectフックを使った副作用処理</strong>と<strong>ローカルストレージによるデータ永続化</strong></p>



<p>について学びます。</p>


<div class="swell-block-postLink">			<div class="p-blogCard -internal" data-type="type2" data-onclick="clickLink">
				<div class="p-blogCard__inner">
					<span class="p-blogCard__caption">前回の記事</span>
					<div class="p-blogCard__thumb c-postThumb"><figure class="c-postThumb__figure"><img decoding="async" src="https://kekenta-it-blog.com/wp-content/uploads/2025/07/eye-catch__react-todo-app-edit-delete-crud__15510-300x169.jpg" alt="" class="c-postThumb__img u-obf-cover" width="320" height="180"></figure></div>					<div class="p-blogCard__body">
						<a class="p-blogCard__title" href="https://kekenta-it-blog.com/react-todo-app-edit-delete-crud/">【React×TODOアプリ】編集・削除機能の実装【基本編：第6回】</a>
											</div>
				</div>
			</div>
		</div>


<p><a href="https://kekenta-it-blog.com/react-todo-app-edit-delete-crud/">前回</a>は<strong>編集・削除機能を追加し、基本的なCRUD操作を完成</strong>させました。今回は、TODOリストの保存や、実用的な副作用処理の基礎を身につけていきます。</p>



<p>これにより、アプリのデータを永続化ができるようになります。</p>



<div class="swell-block-capbox cap_box"><div class="cap_box_ttl"><span><span style="--the-icon-svg: url(data:image/svg+xml;base64,PHN2ZyBoZWlnaHQ9IjFlbSIgd2lkdGg9IjFlbSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiBhcmlhLWhpZGRlbj0idHJ1ZSIgdmlld0JveD0iMCAwIDQ4IDQ4Ij48cGF0aCBkPSJNMzIgNDYuNUgxNmMtMS4xIDAtMi0uOS0yLTJzLjktMiAyLTJoMTZjMS4xIDAgMiAuOSAyIDJzLS45IDItMiAyek00MS43IDE1LjlDNDEuMyAxMyA0MCAxMC4zIDM4LjIgOCAzNC41IDMuMiAyOSAuOCAyMy4xIDEgMTQgMS40IDYuNSA4LjkgNiAxOGMtLjMgNiAyLjQgMTEuNyA3LjIgMTUuNC41LjQuOC45LjggMS41djEuNmMwIDIuMiAxLjggNCA0IDRoMTJjMi4yIDAgNC0xLjggNC00VjM1YzAtLjYuMy0xLjIuOS0xLjcgNS4zLTQgOC0xMC42IDYuOC0xNy40em0tNy4xIDEuN2gtLjNjLS43IDAtMS4zLS41LTEuNS0xLjItLjctMy4yLTMuMi01LjctNi40LTYuMy0uOC0uMS0xLjQtLjktMS4yLTEuN3MuOS0xLjQgMS43LTEuMmM0LjQuOCA4IDQuMiA4LjkgOC42LjEuOC0uNCAxLjYtMS4yIDEuOHoiPjwvcGF0aD48L3N2Zz4=)" data-icon="LsLightbulb" data-id="0" aria-hidden="true" class="swl-inline-icon"> </span> <strong>この記事でわかること</strong></span></div><div class="cap_box_content">
<ul class="wp-block-list is-style-check_list -list-under-dashed">
<li>useEffectフックの基本的な使い方</li>



<li>副作用（サイドエフェクト）とは何か</li>



<li>ローカルストレージへの保存・読み込み</li>
</ul>
</div></div>


<div class="wp-block-image is-style-browser_mac size_xs">
<figure class="aligncenter size-large"><img decoding="async" width="1024" height="602" src="https://kekenta-it-blog.com/wp-content/uploads/2025/07/react_todo_series_07_01-1024x602.jpg" alt="TODOアプリ（第７回：完成イメージ）その①" class="wp-image-15542" srcset="https://kekenta-it-blog.com/wp-content/uploads/2025/07/react_todo_series_07_01-1024x602.jpg 1024w, https://kekenta-it-blog.com/wp-content/uploads/2025/07/react_todo_series_07_01-300x176.jpg 300w, https://kekenta-it-blog.com/wp-content/uploads/2025/07/react_todo_series_07_01-768x452.jpg 768w, https://kekenta-it-blog.com/wp-content/uploads/2025/07/react_todo_series_07_01.jpg 1107w" sizes="(max-width: 1024px) 100vw, 1024px" /><figcaption class="wp-element-caption">TODOアプリ（第７回：完成イメージ）その①</figcaption></figure>
</div>


<p class="is-style-balloon_box"><span style="--the-icon-svg: url(data:image/svg+xml;base64,PHN2ZyBoZWlnaHQ9IjFlbSIgd2lkdGg9IjFlbSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiBhcmlhLWhpZGRlbj0idHJ1ZSIgdmlld0JveD0iMCAwIDQ4IDQ4Ij48cGF0aCBkPSJNMTAgM2gyOGMxLjEgMCAyIC45IDIgMnYzOS42YzAgLjktMS4xIDEuMy0xLjcuN0wyNCAzMSA5LjcgNDUuM2MtLjYuNi0xLjcuMi0xLjctLjdWNWMwLTEuMS45LTIgMi0yeiI+PC9wYXRoPjwvc3ZnPg==)" data-icon="LsBookmark" data-id="0" aria-hidden="true" class="swl-inline-icon"> </span> <strong>TODOアプリ開発シリーズのまとめ記事はこちら</strong></p>


<div class="swell-block-postLink">			<div class="p-blogCard -internal" data-type="type2" data-onclick="clickLink">
				<div class="p-blogCard__inner">
					<span class="p-blogCard__caption">シリーズ完全ガイド</span>
					<div class="p-blogCard__thumb c-postThumb"><figure class="c-postThumb__figure"><img decoding="async" src="https://kekenta-it-blog.com/wp-content/uploads/2025/07/eye-catch__react-todo-app-series-complete-guide-summary__15557-300x169.jpg" alt="" class="c-postThumb__img u-obf-cover" width="320" height="180"></figure></div>					<div class="p-blogCard__body">
						<a class="p-blogCard__title" href="https://kekenta-it-blog.com/react-todo-app-series-complete-guide-summary/">【React】初心者向けTODOアプリ開発シリーズ &#8211; 完全ガイドまとめ</a>
											</div>
				</div>
			</div>
		</div>


<h2 class="wp-block-heading">前回までのコード</h2>



<p>第6回までで作成・修正したファイル構成と主要なコードは以下の通りです。</p>



<h3 class="wp-block-heading">ファイル構成</h3>



<div class="hcb_wrap"><pre class="prism line-numbers lang-plain"><code>todo-app/
├── src/
│   ├── App.js
│   ├── App.css
│   ├── TodoItem.js
│   ├── TodoList.js
│   ├── TodoHeader.js
│   ├── TodoForm.js
│   └── TodoFilter.js</code></pre></div>



<h3 class="wp-block-heading">TodoItem.js</h3>



<div class="hcb_wrap"><pre class="prism line-numbers lang-js" data-lang="JavaScript"><code>import React, { useState } from &#39;react&#39;;

function TodoItem({ id, text, completed, priority = &quot;medium&quot;, onToggle, onDelete, onEdit }) {
  const [isEditing, setIsEditing] = useState(false);
  const [editText, setEditText] = useState(text);

  const handleEdit = () =&gt; {
    setIsEditing(true);
    setEditText(text);
  };

  const handleSave = () =&gt; {
    if (editText.trim()) {
      onEdit(id, editText);
      setIsEditing(false);
    }
  };

  const handleCancel = () =&gt; {
    setIsEditing(false);
    setEditText(text);
  };

  const handleKeyDown = (event) =&gt; {
    if (event.key === &#39;Enter&#39;) {
      handleSave();
    }
    if (event.key === &#39;Escape&#39;) {
      handleCancel();
    }
  };

  return (
    &lt;div className={`todo-item priority-${priority}`}&gt;
      &lt;input
        type=&quot;checkbox&quot;
        checked={completed}
        onChange={() =&gt; onToggle(id)}
      /&gt;
      {isEditing ? (
        &lt;div className=&quot;edit-section&quot;&gt;
          &lt;input
            type=&quot;text&quot;
            value={editText}
            onChange={(e) =&gt; setEditText(e.target.value)}
            onKeyDown={handleKeyDown}
            className=&quot;edit-input&quot;
            autoFocus
          /&gt;
          &lt;button onClick={handleSave} className=&quot;save-button&quot;&gt;保存&lt;/button&gt;
          &lt;button onClick={handleCancel} className=&quot;cancel-button&quot;&gt;キャンセル&lt;/button&gt;
        &lt;/div&gt;
      ) : (
        &lt;div className=&quot;todo-content&quot;&gt;
          &lt;span style={{ textDecoration: completed ? &#39;line-through&#39; : &#39;none&#39; }}&gt;{text}&lt;/span&gt;
          &lt;span className={`priority-badge ${priority}`}&gt;{priority === &#39;high&#39; ? &#39;高&#39; : priority === &#39;medium&#39; ? &#39;中&#39; : &#39;低&#39;}&lt;/span&gt;
          &lt;div className=&quot;todo-actions&quot;&gt;
            &lt;button onClick={handleEdit} className=&quot;edit-button&quot;&gt;編集&lt;/button&gt;
            &lt;button onClick={() =&gt; onDelete(id)} className=&quot;delete-button&quot;&gt;削除&lt;/button&gt;
          &lt;/div&gt;
        &lt;/div&gt;
      )}
    &lt;/div&gt;
  );
}

export default TodoItem;</code></pre></div>



<h3 class="wp-block-heading">TodoList.js</h3>



<div class="hcb_wrap"><pre class="prism line-numbers lang-js" data-lang="JavaScript"><code>import React from &#39;react&#39;;
import TodoItem from &#39;./TodoItem&#39;;

function TodoList({ todos, onToggle, onDelete, onEdit }) {
  if (todos.length === 0) {
    return (
      &lt;div className=&quot;empty-state&quot;&gt;
        &lt;p&gt;TODOがありません。新しいTODOを追加してください。&lt;/p&gt;
      &lt;/div&gt;
    );
  }
  return (
    &lt;div className=&quot;todo-list&quot;&gt;
      {todos.map((todo) =&gt; (
        &lt;TodoItem
          key={todo.id}
          id={todo.id}
          text={todo.text}
          completed={todo.completed}
          priority={todo.priority}
          onToggle={onToggle}
          onDelete={onDelete}
          onEdit={onEdit}
        /&gt;
      ))}
    &lt;/div&gt;
  );
}

export default TodoList;</code></pre></div>



<h3 class="wp-block-heading">App.js</h3>



<div class="hcb_wrap"><pre class="prism line-numbers lang-js" data-lang="JavaScript"><code>import React, { useState } from &#39;react&#39;;
import &#39;./App.css&#39;;
import TodoHeader from &#39;./TodoHeader&#39;;
import TodoList from &#39;./TodoList&#39;;
import TodoForm from &#39;./TodoForm&#39;;
import TodoFilter from &#39;./TodoFilter&#39;;

function App() {
  const [todos, setTodos] = useState([
    { id: 1, text: &quot;Reactを学ぶ&quot;, completed: false, priority: &quot;high&quot; },
    { id: 2, text: &quot;TODOアプリを作る&quot;, completed: true, priority: &quot;medium&quot; },
    { id: 3, text: &quot;データベース連携&quot;, completed: false, priority: &quot;low&quot; },
    { id: 4, text: &quot;デプロイする&quot;, completed: false, priority: &quot;medium&quot; }
  ]);
  const [filter, setFilter] = useState(&#39;all&#39;);

  const filteredTodos = todos.filter(todo =&gt; {
    if (filter === &#39;all&#39;) return true;
    if (filter === &#39;completed&#39;) return todo.completed;
    if (filter === &#39;pending&#39;) return !todo.completed;
    return true;
  });

  const completedCount = todos.filter(todo =&gt; todo.completed).length;

  const toggleTodo = (id) =&gt; {
    setTodos(prevTodos =&gt;
      prevTodos.map(todo =&gt;
        todo.id === id
          ? { ...todo, completed: !todo.completed }
          : todo
      )
    );
  };

  const addTodo = (newTodo) =&gt; {
    setTodos(prevTodos =&gt; [...prevTodos, newTodo]);
  };

  const deleteTodo = (id) =&gt; {
    setTodos(prevTodos =&gt; prevTodos.filter(todo =&gt; todo.id !== id));
  };

  const editTodo = (id, newText) =&gt; {
    setTodos(prevTodos =&gt;
      prevTodos.map(todo =&gt;
        todo.id === id
          ? { ...todo, text: newText }
          : todo
      )
    );
  };

  return (
    &lt;div className=&quot;App&quot;&gt;
      &lt;TodoHeader
        title=&quot;React TODOアプリ&quot;
        totalCount={todos.length}
        completedCount={completedCount}
      /&gt;
      &lt;TodoForm onAddTodo={addTodo} /&gt;
      &lt;TodoFilter
        filter={filter}
        onFilterChange={setFilter}
        totalCount={todos.length}
        activeCount={todos.filter(todo =&gt; !todo.completed).length}
        completedCount={completedCount}
      /&gt;
      &lt;TodoList
        todos={filteredTodos}
        onToggle={toggleTodo}
        onDelete={deleteTodo}
        onEdit={editTodo}
      /&gt;
    &lt;/div&gt;
  );
}

export default App;</code></pre></div>



<h3 class="wp-block-heading">App.css</h3>



<div class="hcb_wrap"><pre class="prism line-numbers lang-css" data-lang="CSS"><code>.edit-section {
  display: flex;
  align-items: center;
  gap: 8px;
  flex: 1;
}
.edit-input {
  flex: 1;
  padding: 8px 12px;
  border: 2px solid #007bff;
  border-radius: 4px;
  font-size: 14px;
  outline: none;
}
.save-button {
  padding: 6px 12px;
  background-color: #28a745;
  color: white;
  border: none;
  border-radius: 4px;
  cursor: pointer;
  font-size: 12px;
}
.save-button:hover {
  background-color: #218838;
}
.cancel-button {
  padding: 6px 12px;
  background-color: #6c757d;
  color: white;
  border: none;
  border-radius: 4px;
  cursor: pointer;
  font-size: 12px;
}
.cancel-button:hover {
  background-color: #5a6268;
}
.todo-actions {
  display: flex;
  gap: 8px;
  margin-left: auto;
}
.edit-button {
  padding: 4px 8px;
  background-color: #ffc107;
  color: #212529;
  border: none;
  border-radius: 4px;
  cursor: pointer;
  font-size: 12px;
}
.edit-button:hover {
  background-color: #e0a800;
}
.delete-button {
  padding: 4px 8px;
  background-color: #dc3545;
  color: white;
  border: none;
  border-radius: 4px;
  cursor: pointer;
  font-size: 12px;
}
.delete-button:hover {
  background-color: #c82333;
}</code></pre></div>


<script async src="https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js?client=ca-pub-4374558503914683"
     crossorigin="anonymous"></script>
<!-- ディスプレイ【横長】 -->
<ins class="adsbygoogle"
     style="display:block"
     data-ad-client="ca-pub-4374558503914683"
     data-ad-slot="9744298852"
     data-ad-format="auto"
     data-full-width-responsive="true"></ins>
<script>
     (adsbygoogle = window.adsbygoogle || []).push({});
</script>



<h2 class="wp-block-heading">useEffectと副作用の基礎</h2>



<p class="is-style-bg_stripe">編集・削除機能を実装する前に、必要な前提知識を整理しておきましょう。</p>



<h3 class="wp-block-heading">副作用（サイドエフェクト）とは</h3>



<p>レンダリング以外の処理（データ取得、ローカルストレージ操作、タイマー設定など）のことを指します。</p>



<h3 class="wp-block-heading">useEffectの基本構文</h3>



<div class="hcb_wrap"><pre class="prism line-numbers lang-js" data-lang="JavaScript"><code>import { useEffect } from &#39;react&#39;;

useEffect(() =&gt; {
  // 副作用処理
  return () =&gt; {
    // クリーンアップ処理（省略可）
  };
}, [依存配列]);</code></pre></div>



<div class="wp-block-group is-style-big_icon_point"><div class="wp-block-group__inner-container is-layout-constrained wp-block-group-is-layout-constrained">
<ul class="wp-block-list is-style-check_list">
<li>依存配列が空：マウント時のみ実行</li>



<li>依存配列に値：その値が変化したときに実行</li>
</ul>
</div></div>



<div class="swell-block-capbox cap_box is-style-onborder_ttl2"><div class="cap_box_ttl"><span><span style="--the-icon-svg: url(data:image/svg+xml;base64,PHN2ZyBoZWlnaHQ9IjFlbSIgd2lkdGg9IjFlbSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiBhcmlhLWhpZGRlbj0idHJ1ZSIgdmlld0JveD0iMCAwIDQ4IDQ4Ij48cGF0aCBkPSJNMzIgNDYuNUgxNmMtMS4xIDAtMi0uOS0yLTJzLjktMiAyLTJoMTZjMS4xIDAgMiAuOSAyIDJzLS45IDItMiAyek00MS43IDE1LjlDNDEuMyAxMyA0MCAxMC4zIDM4LjIgOCAzNC41IDMuMiAyOSAuOCAyMy4xIDEgMTQgMS40IDYuNSA4LjkgNiAxOGMtLjMgNiAyLjQgMTEuNyA3LjIgMTUuNC41LjQuOC45LjggMS41djEuNmMwIDIuMiAxLjggNCA0IDRoMTJjMi4yIDAgNC0xLjggNC00VjM1YzAtLjYuMy0xLjIuOS0xLjcgNS4zLTQgOC0xMC42IDYuOC0xNy40em0tNy4xIDEuN2gtLjNjLS43IDAtMS4zLS41LTEuNS0xLjItLjctMy4yLTMuMi01LjctNi40LTYuMy0uOC0uMS0xLjQtLjktMS4yLTEuN3MuOS0xLjQgMS43LTEuMmM0LjQuOCA4IDQuMiA4LjkgOC42LjEuOC0uNCAxLjYtMS4yIDEuOHoiPjwvcGF0aD48L3N2Zz4=)" data-icon="LsLightbulb" data-id="0" aria-hidden="true" class="swl-inline-icon"> </span> <strong>マウントとは？</strong></span></div><div class="cap_box_content">
<p>Reactにおける<strong>マウント</strong>とは、コンポーネントが画面上に初めて表示されるタイミングのことを指します。Reactでは、コンポーネントが生成されてDOMに追加されることを「マウント」と呼びます。</p>
</div></div>



<h4 class="wp-block-heading">【サンプル】useEffectでコンソールにメッセージを表示</h4>



<div class="hcb_wrap"><pre class="prism line-numbers lang-js" data-lang="JavaScript"><code>import React, { useEffect } from &#39;react&#39;;

function SampleComponent() {
  useEffect(() =&gt; {
    console.log(&#39;コンポーネントがマウントされました&#39;);
    return () =&gt; {
      console.log(&#39;コンポーネントがアンマウントされました&#39;);
    };
  }, []);

  return &lt;div&gt;useEffectのサンプル&lt;/div&gt;;
}</code></pre></div>


<script async src="https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js?client=ca-pub-4374558503914683"
     crossorigin="anonymous"></script>
<!-- ディスプレイ【横長】 -->
<ins class="adsbygoogle"
     style="display:block"
     data-ad-client="ca-pub-4374558503914683"
     data-ad-slot="9744298852"
     data-ad-format="auto"
     data-full-width-responsive="true"></ins>
<script>
     (adsbygoogle = window.adsbygoogle || []).push({});
</script>



<h2 class="wp-block-heading">ローカルストレージとは？</h2>



<p>ローカルストレージは、<strong>Webブラウザにデータを保存できる仕組み</strong>です。保存したデータはページをリロードしたり、ブラウザを閉じたりしても消えずに残ります。これにより、ユーザーが入力した情報やアプリの状態を永続的に保持することができます。</p>



<p>例えば、TODOリストの内容をローカルストレージに保存しておけば、次回アクセス時にも前回のリストがそのまま表示されるようになります。</p>



<h3 class="wp-block-heading">保存先と確認方法</h3>



<ul class="wp-block-list is-style-check_list -list-under-dashed">
<li>ローカルストレージの保存先は、各ブラウザのlocalStorage領域です。</li>



<li>Chromeの場合、F12キーで開発者ツールを開き、「Application」タブ → 「Storage」→「Local Storage」→該当ドメインを選択すると、保存されているデータを確認・編集できます。</li>



<li>保存キー（例：todos）や値（JSON形式）もここで直接確認できます。</li>
</ul>



<div class="wp-block-group is-style-big_icon_caution"><div class="wp-block-group__inner-container is-layout-constrained wp-block-group-is-layout-constrained">
<ul class="wp-block-list is-style-check_list">
<li>ローカルストレージには保存容量（一般的に5MB程度）の制限があります。</li>



<li>同じドメイン内のページであればデータは共有されますが、他のブラウザや端末とは共有されません。</li>



<li>セキュリティ上、パスワードや個人情報などの機密データは保存しないようにしましょう。</li>



<li>ユーザーが手動でローカルストレージを削除することも可能です。</li>
</ul>
</div></div>



<h2 class="wp-block-heading">【実践】ローカルストレージへのTODO保存・復元</h2>



<p class="is-style-bg_stripe">ここからは、実際に手を動かして、TODOリストをローカルストレージに保存・復元する機能を追加していきましょう。</p>



<h3 class="wp-block-heading">App.jsの修正</h3>



<div class="hcb_wrap"><pre class="prism line-numbers lang-js" data-lang="JavaScript"><code>import React, { useState, useEffect } from &#39;react&#39;;
// ...既存のimport

function App() {
  const [todos, setTodos] = useState(() =&gt; {
    // 初回マウント時にローカルストレージから読み込み
    const saved = localStorage.getItem(&#39;todos&#39;);
    return saved ? JSON.parse(saved) : [];
  });

  // ...他のstateや関数

  // todosが変化するたびにローカルストレージへ保存
  useEffect(() =&gt; {
    localStorage.setItem(&#39;todos&#39;, JSON.stringify(todos));
  }, [todos]);

  // ...JSXはこれまで通り
}</code></pre></div>


<script async src="https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js?client=ca-pub-4374558503914683"
     crossorigin="anonymous"></script>
<!-- ディスプレイ【横長】 -->
<ins class="adsbygoogle"
     style="display:block"
     data-ad-client="ca-pub-4374558503914683"
     data-ad-slot="9744298852"
     data-ad-format="auto"
     data-full-width-responsive="true"></ins>
<script>
     (adsbygoogle = window.adsbygoogle || []).push({});
</script>



<h2 class="wp-block-heading">動作確認</h2>



<p>実装が完了したら、以下の点を確認してください。</p>


<div class="wp-block-image is-style-browser_mac size_xs">
<figure class="aligncenter size-large"><img decoding="async" width="1024" height="602" src="https://kekenta-it-blog.com/wp-content/uploads/2025/07/react_todo_series_07_01-1024x602.jpg" alt="TODOアプリ（第７回：完成イメージ）その①" class="wp-image-15542" srcset="https://kekenta-it-blog.com/wp-content/uploads/2025/07/react_todo_series_07_01-1024x602.jpg 1024w, https://kekenta-it-blog.com/wp-content/uploads/2025/07/react_todo_series_07_01-300x176.jpg 300w, https://kekenta-it-blog.com/wp-content/uploads/2025/07/react_todo_series_07_01-768x452.jpg 768w, https://kekenta-it-blog.com/wp-content/uploads/2025/07/react_todo_series_07_01.jpg 1107w" sizes="(max-width: 1024px) 100vw, 1024px" /><figcaption class="wp-element-caption">TODOアプリ（第７回：完成イメージ）その①</figcaption></figure>
</div>

<div class="wp-block-image is-style-browser_mac size_s">
<figure class="aligncenter size-large"><img decoding="async" width="1024" height="421" src="https://kekenta-it-blog.com/wp-content/uploads/2025/07/image-1024x421.png" alt="TODOアプリ（第７回：完成イメージ）その①" class="wp-image-15547" srcset="https://kekenta-it-blog.com/wp-content/uploads/2025/07/image-1024x421.png 1024w, https://kekenta-it-blog.com/wp-content/uploads/2025/07/image-300x123.png 300w, https://kekenta-it-blog.com/wp-content/uploads/2025/07/image-768x316.png 768w, https://kekenta-it-blog.com/wp-content/uploads/2025/07/image.png 1421w" sizes="(max-width: 1024px) 100vw, 1024px" /><figcaption class="wp-element-caption">TODOアプリ（第７回：完成イメージ）その①</figcaption></figure>
</div>


<div class="wp-block-group is-style-big_icon_good"><div class="wp-block-group__inner-container is-layout-constrained wp-block-group-is-layout-constrained">
<ul class="wp-block-list is-style-check_list -list-under-dashed">
<li>TODOを追加・編集・削除しても、ページをリロードしても内容が保持される</li>



<li>ローカルストレージに「todos」というキーでデータが保存されている</li>
</ul>
</div></div>



<h2 class="wp-block-heading">FAQ</h2>



<dl class="swell-block-faq -icon-circle is-style-faq-border" data-q="fill-custom" data-a="fill-main">
<div class="swell-block-faq__item"><dt class="faq_q">ローカルストレージに保存されない場合</dt><dd class="faq_a">
<p>localStorageのキー名やJSONの扱い、useEffectの依存配列が正しいか確認してください。</p>
</dd></div>



<div class="swell-block-faq__item"><dt class="faq_q">useEffectが何度も実行される場合</dt><dd class="faq_a">
<p>依存配列の指定が正しいか確認してください。</p>
</dd></div>
</dl>


<script async src="https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js?client=ca-pub-4374558503914683"
     crossorigin="anonymous"></script>
<!-- ディスプレイ【横長】 -->
<ins class="adsbygoogle"
     style="display:block"
     data-ad-client="ca-pub-4374558503914683"
     data-ad-slot="9744298852"
     data-ad-format="auto"
     data-full-width-responsive="true"></ins>
<script>
     (adsbygoogle = window.adsbygoogle || []).push({});
</script>



<h2 class="wp-block-heading">まとめ</h2>



<p>今回は、useEffectフックを使った副作用処理と、ローカルストレージへのTODO保存・復元を実装しました。</p>



<ul class="wp-block-list is-style-check_list -list-under-dashed">
<li>useEffectの基本的な使い方</li>



<li>副作用の概念</li>



<li>ローカルストレージとの連携</li>



<li>クリーンアップ処理の実装</li>
</ul>


<div class="swell-block-balloon"><div class="c-balloon -bln-left" data-col="gray"><div class="c-balloon__icon -circle"><img decoding="async" src="data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==" data-src="https://kekenta-it-blog.com/wp-content/uploads/2023/11/kekenta-icon-150x150.jpg" alt="" class="lazyload c-balloon__iconImg" width="80px" height="80px"><noscript><img decoding="async" src="https://kekenta-it-blog.com/wp-content/uploads/2023/11/kekenta-icon-150x150.jpg" alt="" class="c-balloon__iconImg" width="80px" height="80px"></noscript><span class="c-balloon__iconName">ケケンタ</span></div><div class="c-balloon__body -speaking -border-on"><div class="c-balloon__text">
<p>これでついに「ReactのTODOアプリ開発シリーズの基本編」は最後の記事を迎えました！<br>ここまで本当にお疲れ様でした！</p>
<span class="c-balloon__shapes"><span class="c-balloon__before"></span><span class="c-balloon__after"></span></span></div></div></div></div>


<p>ここまでの内容で、TODOアプリに必要な最低限の機能は実装することができました。</p>



<p class="is-style-icon_pen">さらなるスキルアップを目指す方は、このTODOアプリを<strong>自分なりにカスタマイズしていく</strong>とよりReactへの理解を深めることができるかと思います。</p>



<p>なお、本シリーズは次回から「発展編」へ突入します。「基本編」で作成したTODOアプリをベースに、API連携やデータベース連携など、<strong>さらなる発展的な技術</strong>を学習していきます。</p>



<p>「発展編 第１回」となる次回の記事では、<strong>CSS-in-JSを活用したスタイリングとUI/UX改善</strong>に挑戦していきます。</p>



<p>次回もどうぞお楽しみに！</p>



<p class="is-style-icon_pen">次回「第８回（発展編 第１回）」の記事は鋭意制作中です。</p>


<div class="p-blogParts post_content" data-partsID="15579">
<hr class="wp-block-separator has-alpha-channel-opacity"/>



<p class="is-style-balloon_box"><span style="--the-icon-svg: url(data:image/svg+xml;base64,PHN2ZyBoZWlnaHQ9IjFlbSIgd2lkdGg9IjFlbSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiBhcmlhLWhpZGRlbj0idHJ1ZSIgdmlld0JveD0iMCAwIDQ4IDQ4Ij48cGF0aCBkPSJNMTEuNyAxLjQgNi44IDVjLS41LjQtLjggMS0uOCAxLjZ2MjguN2MwIC44LjUgMS41IDEuMiAxLjhsMjQgMTAuM2MxLjMuNiAyLjgtLjQgMi44LTEuOFYxOWMwLS44LS41LTEuNS0xLjItMS44TDEwLjIgNy41bDIuOS0yLjJjLjktLjYgMi0uOCAzLS40bDIwLjYgOC44Yy43LjMgMS4yIDEgMS4yIDEuOFY0Mi45YzAgLjkgMSAxLjMgMS43LjhsMS43LTEuNWMuNC0uNC43LS45LjctMS41VjEzYzAtLjgtLjUtMS41LTEuMi0xLjhMMTYuNy44Yy0xLjctLjctMy42LS41LTUgLjZ6Ij48L3BhdGg+PC9zdmc+)" data-icon="LsBook" data-id="0" aria-hidden="true" class="swl-inline-icon">  </span> <strong>僕が実際にReact学習に使用した書籍です</strong></p>


<div id="rinkerid15577" class="yyi-rinker-contents  yyi-rinker-postid-15577 yyi-rinker-img-m yyi-rinker-catid-256 ">
	<div class="yyi-rinker-box">
		<div class="yyi-rinker-image">
							<a href="https://www.amazon.co.jp/dp/B09BV2HGN3?tag=kekenta03am0b-22&#038;linkCode=ogi&#038;th=1&#038;psc=1" rel="nofollow" class="yyi-rinker-tracking"  data-click-tracking="amazon_img 15577 モダンJavaScriptの基本から始める　React実践の教科書　（最新ReactHooks対応）" data-vars-click-id="amazon_img 15577 モダンJavaScriptの基本から始める　React実践の教科書　（最新ReactHooks対応）"><img decoding="async" src="https://m.media-amazon.com/images/I/51Y0-P+m94L._SL160_.jpg"  width="112" height="160" class="yyi-rinker-main-img" style="border: none;"></a>					</div>
		<div class="yyi-rinker-info">
			<div class="yyi-rinker-title">
									<a href="https://www.amazon.co.jp/dp/B09BV2HGN3?tag=kekenta03am0b-22&#038;linkCode=ogi&#038;th=1&#038;psc=1" rel="nofollow" class="yyi-rinker-tracking" data-click-tracking="amazon_title 15577 モダンJavaScriptの基本から始める　React実践の教科書　（最新ReactHooks対応）" data-vars-amp-click-id="amazon_title 15577 モダンJavaScriptの基本から始める　React実践の教科書　（最新ReactHooks対応）" >モダンJavaScriptの基本から始める　React実践の教科書　（最新ReactHooks対応）</a>							</div>
			<div class="yyi-rinker-detail">
							<div class="credit-box">created by&nbsp;<a href="https://oyakosodate.com/rinker/" rel="nofollow noopener" target="_blank" >Rinker</a></div>
										<div class="price-box">
							</div>
						</div>
						<ul class="yyi-rinker-links">
																	<li class="amazonkindlelink">
						<a href="https://www.amazon.co.jp/dp/B09BV2HGN3?tag=kekenta03am0b-22&amp;linkCode=ogi&amp;th=1&amp;psc=1" rel="nofollow" class="yyi-rinker-link yyi-rinker-tracking"  data-click-tracking="amazon_kindle 15577 モダンJavaScriptの基本から始める　React実践の教科書　（最新ReactHooks対応）"  data-vars-amp-click-id="amazon_kindle 15577 モダンJavaScriptの基本から始める　React実践の教科書　（最新ReactHooks対応）">Kindle</a>					</li>
								                    <li class="amazonlink">
						<a href="https://www.amazon.co.jp/dp/B09BV2HGN3?tag=kekenta03am0b-22&amp;linkCode=ogi&amp;th=1&amp;psc=1" rel="nofollow" class="yyi-rinker-link yyi-rinker-tracking"  data-click-tracking="amazon 15577 モダンJavaScriptの基本から始める　React実践の教科書　（最新ReactHooks対応）"  data-vars-amp-click-id="amazon 15577 モダンJavaScriptの基本から始める　React実践の教科書　（最新ReactHooks対応）">Amazon</a>					</li>
													<li class="rakutenlink">
						<a href="https://hb.afl.rakuten.co.jp/hgc/3ace225e.aaf54072.3ace225f.2cf27f19/Rinker_o_20250722203529?pc=https%3A%2F%2Fsearch.rakuten.co.jp%2Fsearch%2Fmall%2F%25E3%2583%25A2%25E3%2583%2580%25E3%2583%25B3JavaScript%25E3%2581%25AE%25E5%259F%25BA%25E6%259C%25AC%25E3%2581%258B%25E3%2582%2589%25E5%25A7%258B%25E3%2582%2581%25E3%2582%258B%25E3%2580%2580React%25E5%25AE%259F%25E8%25B7%25B5%25E3%2581%25AE%25E6%2595%2599%25E7%25A7%2591%25E6%259B%25B8%25E3%2580%2580%25EF%25BC%2588%25E6%259C%2580%25E6%2596%25B0ReactHooks%25E5%25AF%25BE%25E5%25BF%259C%25EF%25BC%2589%2F%3Ff%3D1%26grp%3Dproduct&amp;m=https%3A%2F%2Fsearch.rakuten.co.jp%2Fsearch%2Fmall%2F%25E3%2583%25A2%25E3%2583%2580%25E3%2583%25B3JavaScript%25E3%2581%25AE%25E5%259F%25BA%25E6%259C%25AC%25E3%2581%258B%25E3%2582%2589%25E5%25A7%258B%25E3%2582%2581%25E3%2582%258B%25E3%2580%2580React%25E5%25AE%259F%25E8%25B7%25B5%25E3%2581%25AE%25E6%2595%2599%25E7%25A7%2591%25E6%259B%25B8%25E3%2580%2580%25EF%25BC%2588%25E6%259C%2580%25E6%2596%25B0ReactHooks%25E5%25AF%25BE%25E5%25BF%259C%25EF%25BC%2589%2F%3Ff%3D1%26grp%3Dproduct" rel="nofollow" class="yyi-rinker-link yyi-rinker-tracking"  data-click-tracking="rakuten 15577 モダンJavaScriptの基本から始める　React実践の教科書　（最新ReactHooks対応）"  data-vars-amp-click-id="rakuten 15577 モダンJavaScriptの基本から始める　React実践の教科書　（最新ReactHooks対応）">楽天市場</a>					</li>
								                											</ul>
					</div>
	</div>
</div>
</div>
]]></content:encoded>
					
					<wfw:commentRss>https://kekenta-it-blog.com/react-todo-app-useeffect-localstrage/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>【React×TODOアプリ】編集・削除機能の実装【基本編：第6回】</title>
		<link>https://kekenta-it-blog.com/react-todo-app-edit-delete-crud/</link>
					<comments>https://kekenta-it-blog.com/react-todo-app-edit-delete-crud/#respond</comments>
		
		<dc:creator><![CDATA[ケケンタ]]></dc:creator>
		<pubDate>Mon, 21 Jul 2025 22:21:00 +0000</pubDate>
				<category><![CDATA[React]]></category>
		<category><![CDATA[Javascript]]></category>
		<category><![CDATA[TODOアプリ]]></category>
		<category><![CDATA[開発シリーズ]]></category>
		<guid isPermaLink="false">https://kekenta-it-blog.com/?p=15510</guid>

					<description><![CDATA[<p><img src="https://kekenta-it-blog.com/wp-content/uploads/2025/07/eye-catch__react-todo-app-edit-delete-crud__15510-1024x576.jpg" class="webfeedsFeaturedVisual" /></p>Reactで作るTODOアプリ開発シリーズ第６回 この記事では、 「編集」と「削除」機能 を追加し、基本的なCRUD操作を完成させます。 前回はリスト表示と条件付きレンダリングについて学習しました。今回は、ユーザーがTO [&#8230;]]]></description>
										<content:encoded><![CDATA[<p><img src="https://kekenta-it-blog.com/wp-content/uploads/2025/07/eye-catch__react-todo-app-edit-delete-crud__15510-1024x576.jpg" class="webfeedsFeaturedVisual" /></p>
<p><strong>Reactで作るTODOアプリ開発シリーズ第６回</strong></p>



<p>この記事では、</p>



<p class="has-text-align-center is-style-big_kakko_box"><strong>「編集」と「削除」機能</strong></p>



<p>を追加し、基本的なCRUD操作を完成させます。</p>


<div class="swell-block-postLink">			<div class="p-blogCard -internal" data-type="type2" data-onclick="clickLink">
				<div class="p-blogCard__inner">
					<span class="p-blogCard__caption">前回の記事</span>
					<div class="p-blogCard__thumb c-postThumb"><figure class="c-postThumb__figure"><img decoding="async" src="https://kekenta-it-blog.com/wp-content/uploads/2025/07/eye-catch__react-list-display-conditional-rendering__15497-300x169.jpg" alt="" class="c-postThumb__img u-obf-cover" width="320" height="180"></figure></div>					<div class="p-blogCard__body">
						<a class="p-blogCard__title" href="https://kekenta-it-blog.com/react-list-display-conditional-rendering/">【React×TODOアプリ】リスト表示と条件付きレンダリング【基本編：第5回】</a>
											</div>
				</div>
			</div>
		</div>


<p>前回は<strong>リスト表示と条件付きレンダリング</strong>について学習しました。今回は、ユーザーがTODOを編集・削除できるようにし、より実用的なアプリに仕上げていきます。</p>



<div class="swell-block-capbox cap_box"><div class="cap_box_ttl"><span><span style="--the-icon-svg: url(data:image/svg+xml;base64,PHN2ZyBoZWlnaHQ9IjFlbSIgd2lkdGg9IjFlbSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiBhcmlhLWhpZGRlbj0idHJ1ZSIgdmlld0JveD0iMCAwIDQ4IDQ4Ij48cGF0aCBkPSJNMzIgNDYuNUgxNmMtMS4xIDAtMi0uOS0yLTJzLjktMiAyLTJoMTZjMS4xIDAgMiAuOSAyIDJzLS45IDItMiAyek00MS43IDE1LjlDNDEuMyAxMyA0MCAxMC4zIDM4LjIgOCAzNC41IDMuMiAyOSAuOCAyMy4xIDEgMTQgMS40IDYuNSA4LjkgNiAxOGMtLjMgNiAyLjQgMTEuNyA3LjIgMTUuNC41LjQuOC45LjggMS41djEuNmMwIDIuMiAxLjggNCA0IDRoMTJjMi4yIDAgNC0xLjggNC00VjM1YzAtLjYuMy0xLjIuOS0xLjcgNS4zLTQgOC0xMC42IDYuOC0xNy40em0tNy4xIDEuN2gtLjNjLS43IDAtMS4zLS41LTEuNS0xLjItLjctMy4yLTMuMi01LjctNi40LTYuMy0uOC0uMS0xLjQtLjktMS4yLTEuN3MuOS0xLjQgMS43LTEuMmM0LjQuOCA4IDQuMiA4LjkgOC42LjEuOC0uNCAxLjYtMS4yIDEuOHoiPjwvcGF0aD48L3N2Zz4=)" data-icon="LsLightbulb" data-id="0" aria-hidden="true" class="swl-inline-icon"> </span> <strong>この記事でわかること</strong></span></div><div class="cap_box_content">
<ul class="wp-block-list is-style-check_list -list-under-dashed">
<li>配列のfilter/mapによるデータ操作</li>



<li>編集・削除機能の実装方法</li>



<li>編集モードの切り替え（条件付きレンダリング）</li>



<li>キーボードイベントの活用</li>



<li>UI/UX向上のための工夫</li>
</ul>
</div></div>


<div class="swell-block-balloon"><div class="c-balloon -bln-left" data-col="gray"><div class="c-balloon__icon -circle"><img decoding="async" src="data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==" data-src="https://kekenta-it-blog.com/wp-content/uploads/2023/07/キリッ-150x150.jpg" alt="" class="lazyload c-balloon__iconImg" width="80px" height="80px"><noscript><img decoding="async" src="https://kekenta-it-blog.com/wp-content/uploads/2023/07/キリッ-150x150.jpg" alt="" class="c-balloon__iconImg" width="80px" height="80px"></noscript><span class="c-balloon__iconName">ケケンタ</span></div><div class="c-balloon__body -speaking -border-on"><div class="c-balloon__text">
<p>編集・削除機能の実装方法を理解することで、CRUD操作を含めたReactアプリの開発が行えるようになります！</p>
<span class="c-balloon__shapes"><span class="c-balloon__before"></span><span class="c-balloon__after"></span></span></div></div></div></div>

<div class="wp-block-image is-style-browser_mac size_xs">
<figure class="aligncenter size-large"><img decoding="async" width="1024" height="655" src="https://kekenta-it-blog.com/wp-content/uploads/2025/07/react_todo_series_06_01-1024x655.jpg" alt="TODOアプリ（第６回：完成イメージ）その①" class="wp-image-15513" srcset="https://kekenta-it-blog.com/wp-content/uploads/2025/07/react_todo_series_06_01-1024x655.jpg 1024w, https://kekenta-it-blog.com/wp-content/uploads/2025/07/react_todo_series_06_01-300x192.jpg 300w, https://kekenta-it-blog.com/wp-content/uploads/2025/07/react_todo_series_06_01-768x491.jpg 768w, https://kekenta-it-blog.com/wp-content/uploads/2025/07/react_todo_series_06_01.jpg 1268w" sizes="(max-width: 1024px) 100vw, 1024px" /><figcaption class="wp-element-caption">TODOアプリ（第６回：完成イメージ）その①</figcaption></figure>
</div>

<div class="wp-block-image is-style-browser_mac size_xs">
<figure class="aligncenter size-large"><img decoding="async" width="1024" height="341" src="https://kekenta-it-blog.com/wp-content/uploads/2025/07/react_todo_series_06_02-1024x341.jpg" alt="TODOアプリ（第６回：完成イメージ）その②" class="wp-image-15514" srcset="https://kekenta-it-blog.com/wp-content/uploads/2025/07/react_todo_series_06_02-1024x341.jpg 1024w, https://kekenta-it-blog.com/wp-content/uploads/2025/07/react_todo_series_06_02-300x100.jpg 300w, https://kekenta-it-blog.com/wp-content/uploads/2025/07/react_todo_series_06_02-768x256.jpg 768w, https://kekenta-it-blog.com/wp-content/uploads/2025/07/react_todo_series_06_02.jpg 1100w" sizes="(max-width: 1024px) 100vw, 1024px" /><figcaption class="wp-element-caption">TODOアプリ（第６回：完成イメージ）その②</figcaption></figure>
</div>

<div class="wp-block-image is-style-browser_mac size_xs">
<figure class="aligncenter size-large"><img decoding="async" width="1024" height="364" src="https://kekenta-it-blog.com/wp-content/uploads/2025/07/react_todo_series_06_03-1024x364.jpg" alt="TODOアプリ（第６回：完成イメージ）その③" class="wp-image-15512" srcset="https://kekenta-it-blog.com/wp-content/uploads/2025/07/react_todo_series_06_03-1024x364.jpg 1024w, https://kekenta-it-blog.com/wp-content/uploads/2025/07/react_todo_series_06_03-300x107.jpg 300w, https://kekenta-it-blog.com/wp-content/uploads/2025/07/react_todo_series_06_03-768x273.jpg 768w, https://kekenta-it-blog.com/wp-content/uploads/2025/07/react_todo_series_06_03.jpg 1047w" sizes="(max-width: 1024px) 100vw, 1024px" /><figcaption class="wp-element-caption">TODOアプリ（第６回：完成イメージ）その③</figcaption></figure>
</div>


<p class="is-style-balloon_box"><span style="--the-icon-svg: url(data:image/svg+xml;base64,PHN2ZyBoZWlnaHQ9IjFlbSIgd2lkdGg9IjFlbSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiBhcmlhLWhpZGRlbj0idHJ1ZSIgdmlld0JveD0iMCAwIDQ4IDQ4Ij48cGF0aCBkPSJNMTAgM2gyOGMxLjEgMCAyIC45IDIgMnYzOS42YzAgLjktMS4xIDEuMy0xLjcuN0wyNCAzMSA5LjcgNDUuM2MtLjYuNi0xLjcuMi0xLjctLjdWNWMwLTEuMS45LTIgMi0yeiI+PC9wYXRoPjwvc3ZnPg==)" data-icon="LsBookmark" data-id="0" aria-hidden="true" class="swl-inline-icon"> </span> <strong>TODOアプリ開発シリーズのまとめ記事はこちら</strong></p>


<div class="swell-block-postLink">			<div class="p-blogCard -internal" data-type="type2" data-onclick="clickLink">
				<div class="p-blogCard__inner">
					<span class="p-blogCard__caption">シリーズ完全ガイド</span>
					<div class="p-blogCard__thumb c-postThumb"><figure class="c-postThumb__figure"><img decoding="async" src="https://kekenta-it-blog.com/wp-content/uploads/2025/07/eye-catch__react-todo-app-series-complete-guide-summary__15557-300x169.jpg" alt="" class="c-postThumb__img u-obf-cover" width="320" height="180"></figure></div>					<div class="p-blogCard__body">
						<a class="p-blogCard__title" href="https://kekenta-it-blog.com/react-todo-app-series-complete-guide-summary/">【React】初心者向けTODOアプリ開発シリーズ &#8211; 完全ガイドまとめ</a>
											</div>
				</div>
			</div>
		</div>


<h2 class="wp-block-heading">前回までのコード</h2>



<p>第5回まで作成・修正したファイル構成と主要なコードは以下の通りです。</p>



<h3 class="wp-block-heading">ファイル構成</h3>



<div class="hcb_wrap"><pre class="prism line-numbers lang-plain"><code>todo-app/
├── src/
│   ├── App.js
│   ├── App.css
│   ├── TodoItem.js
│   ├── TodoList.js
│   ├── TodoHeader.js
│   ├── TodoForm.js
│   └── TodoFilter.js</code></pre></div>



<h3 class="wp-block-heading">App.js</h3>



<div class="hcb_wrap"><pre class="prism line-numbers lang-js" data-lang="JavaScript"><code>import React, { useState } from &#39;react&#39;;
import &#39;./App.css&#39;;
import TodoHeader from &#39;./TodoHeader&#39;;
import TodoList from &#39;./TodoList&#39;;
import TodoForm from &#39;./TodoForm&#39;;
import TodoFilter from &#39;./TodoFilter&#39;;

function App() {
  const [todos, setTodos] = useState([
    { id: 1, text: &quot;Reactを学ぶ&quot;, completed: false, priority: &quot;high&quot; },
    { id: 2, text: &quot;TODOアプリを作る&quot;, completed: true, priority: &quot;medium&quot; },
    { id: 3, text: &quot;データベース連携&quot;, completed: false, priority: &quot;low&quot; },
    { id: 4, text: &quot;デプロイする&quot;, completed: false, priority: &quot;medium&quot; }
  ]);
  const [filter, setFilter] = useState(&#39;all&#39;);

  // フィルタリングされたTODOリスト
  const filteredTodos = todos.filter(todo =&gt; {
    if (filter === &#39;all&#39;) return true;
    if (filter === &#39;completed&#39;) return todo.completed;
    if (filter === &#39;pending&#39;) return !todo.completed;
    return true;
  });

  const completedCount = todos.filter(todo =&gt; todo.completed).length;

  // TODOの完了状態を切り替える関数
  const toggleTodo = (id) =&gt; {
    setTodos(prevTodos =&gt;
      prevTodos.map(todo =&gt;
        todo.id === id
          ? { ...todo, completed: !todo.completed }
          : todo
      )
    );
  };

  // 新しいTODOを追加する関数
  const addTodo = (newTodo) =&gt; {
    setTodos(prevTodos =&gt; [...prevTodos, newTodo]);
  };

  return (
    &lt;div className=&quot;App&quot;&gt;
      &lt;TodoHeader
        title=&quot;React TODOアプリ&quot;
        totalCount={todos.length}
        completedCount={completedCount}
      /&gt;
      &lt;TodoForm onAddTodo={addTodo} /&gt;
      &lt;TodoFilter filter={filter} onFilterChange={setFilter} /&gt;
      &lt;TodoList todos={filteredTodos} onToggle={toggleTodo} /&gt;
    &lt;/div&gt;
  );
}

export default App;</code></pre></div>



<h3 class="wp-block-heading">TodoItem.js</h3>



<div class="hcb_wrap"><pre class="prism line-numbers lang-js" data-lang="JavaScript"><code>import React from &#39;react&#39;;

function TodoItem({ id, text, completed, priority = &quot;medium&quot;, onToggle }) {
  return (
    &lt;div className={`todo-item priority-${priority}`}&gt;
      &lt;input
        type=&quot;checkbox&quot;
        checked={completed}
        onChange={() =&gt; onToggle(id)}
      /&gt;
      &lt;span style={{ textDecoration: completed ? &#39;line-through&#39; : &#39;none&#39; }}&gt;{text}&lt;/span&gt;
      {completed && (
        &lt;span className=&quot;completed-badge&quot;&gt;完了&lt;/span&gt;
      )}
      {!completed && (
        &lt;span className=&quot;pending-badge&quot;&gt;未完了&lt;/span&gt;
      )}
    &lt;/div&gt;
  );
}

export default TodoItem;</code></pre></div>



<h3 class="wp-block-heading">TodoList.js</h3>



<div class="hcb_wrap"><pre class="prism line-numbers lang-js" data-lang="JavaScript"><code>import React from &#39;react&#39;;
import TodoItem from &#39;./TodoItem&#39;;

function TodoList({ todos, onToggle }) {
  if (todos.length === 0) {
    return (
      &lt;div className=&quot;empty-state&quot;&gt;
        &lt;p&gt;TODOがありません。新しいTODOを追加してください。&lt;/p&gt;
      &lt;/div&gt;
    );
  }
  return (
    &lt;div className=&quot;todo-list&quot;&gt;
      {todos.map((todo) =&gt; (
        &lt;TodoItem
          key={todo.id}
          id={todo.id}
          text={todo.text}
          completed={todo.completed}
          priority={todo.priority}
          onToggle={onToggle}
        /&gt;
      ))}
    &lt;/div&gt;
  );
}

export default TodoList;</code></pre></div>



<h3 class="wp-block-heading">TodoFilter.js</h3>



<div class="hcb_wrap"><pre class="prism line-numbers lang-js" data-lang="JavaScript"><code>import React from &#39;react&#39;;

function TodoFilter({ filter, onFilterChange }) {
  return (
    &lt;div className=&quot;todo-filter&quot;&gt;
      &lt;button
        className={`filter-button ${filter === &#39;all&#39; ? &#39;active&#39; : &#39;&#39;}`}
        onClick={() =&gt; onFilterChange(&#39;all&#39;)}
      &gt;
        すべて
      &lt;/button&gt;
      &lt;button
        className={`filter-button ${filter === &#39;pending&#39; ? &#39;active&#39; : &#39;&#39;}`}
        onClick={() =&gt; onFilterChange(&#39;pending&#39;)}
      &gt;
        未完了
      &lt;/button&gt;
      &lt;button
        className={`filter-button ${filter === &#39;completed&#39; ? &#39;active&#39; : &#39;&#39;}`}
        onClick={() =&gt; onFilterChange(&#39;completed&#39;)}
      &gt;
        完了済み
      &lt;/button&gt;
    &lt;/div&gt;
  );
}

export default TodoFilter;</code></pre></div>



<h3 class="wp-block-heading">App.css</h3>



<div class="hcb_wrap"><pre class="prism line-numbers lang-css" data-lang="CSS"><code>.todo-filter {
  display: flex;
  justify-content: center;
  gap: 10px;
  margin-bottom: 20px;
}

.filter-button {
  padding: 8px 16px;
  border: 1px solid #ddd;
  background-color: white;
  border-radius: 4px;
  cursor: pointer;
  transition: all 0.2s;
}

.filter-button:hover {
  background-color: #f8f9fa;
}

.filter-button.active {
  background-color: #007bff;
  color: white;
  border-color: #007bff;
}

.empty-state {
  text-align: center;
  padding: 40px;
  color: #666;
  font-style: italic;
}

.completed-badge {
  background-color: #28a745;
  color: white;
  padding: 2px 8px;
  border-radius: 12px;
  font-size: 12px;
  margin-left: 10px;
}

.pending-badge {
  background-color: #ffc107;
  color: #212529;
  padding: 2px 8px;
  border-radius: 12px;
  font-size: 12px;
  margin-left: 10px;
}</code></pre></div>


<script async src="https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js?client=ca-pub-4374558503914683"
     crossorigin="anonymous"></script>
<!-- ディスプレイ【横長】 -->
<ins class="adsbygoogle"
     style="display:block"
     data-ad-client="ca-pub-4374558503914683"
     data-ad-slot="9744298852"
     data-ad-format="auto"
     data-full-width-responsive="true"></ins>
<script>
     (adsbygoogle = window.adsbygoogle || []).push({});
</script>



<h2 class="wp-block-heading">編集・削除機能の実装に必要な前提知識</h2>



<p class="is-style-bg_stripe">編集・削除機能を実装する前に、必要な前提知識を整理しておきましょう。</p>



<h3 class="wp-block-heading">配列操作の基礎</h3>



<p>編集・削除機能では、配列の<code>filter</code>と<code>map</code>メソッドを活用します。</p>



<h4 class="wp-block-heading">filterメソッド</h4>



<p>配列から条件に合う要素のみを抽出するメソッドです。</p>



<div class="hcb_wrap"><pre class="prism line-numbers lang-js" data-lang="JavaScript"><code>// 削除機能で使用：指定したID以外のTODOを残す
const newTodos = todos.filter(todo =&gt; todo.id !== idToDelete);</code></pre></div>



<h4 class="wp-block-heading">mapメソッド</h4>



<p>配列の各要素を変換するメソッドです。</p>



<div class="hcb_wrap"><pre class="prism line-numbers lang-js" data-lang="JavaScript"><code>// 編集機能で使用：指定したIDのTODOのテキストを更新
const newTodos = todos.map(todo =&gt;
  todo.id === idToEdit
    ? { ...todo, text: newText }
    : todo
);</code></pre></div>



<h3 class="wp-block-heading">イベントの伝播と停止</h3>



<p>編集モードでは、キーボードイベント（Enter、Escape）を活用します。</p>



<p>これにより、ユーザーはマウスを使用しなくてもTODOの追加・編集・キャンセルができるようになるため、ユーザビリティの向上につながります。</p>



<h4 class="wp-block-heading">onKeyDownイベント</h4>



<p>キーが押された瞬間に発火するイベントです。</p>



<div class="hcb_wrap"><pre class="prism line-numbers lang-js" data-lang="JavaScript"><code>const handleKeyDown = (event) =&gt; {
  if (event.key === &#39;Enter&#39;) {
    // 保存処理
  }
  if (event.key === &#39;Escape&#39;) {
    // キャンセル処理
  }
};</code></pre></div>



<h3 class="wp-block-heading">条件付きレンダリングの応用</h3>



<p>編集モードと表示モードを切り替えるために、条件付きレンダリングを活用します。</p>



<div class="hcb_wrap"><pre class="prism line-numbers lang-js" data-lang="JavaScript"><code>{isEditing ? (
  // 編集モードのUI
) : (
  // 表示モードのUI
)}</code></pre></div>



<h2 class="wp-block-heading">【実践】編集・削除機能の実装</h2>



<p class="is-style-bg_stripe">ここからは、実際に手を動かして、TODOの編集・削除機能を追加していきましょう。</p>



<h3 class="wp-block-heading">1. TodoItem.jsの修正</h3>



<p>既存の<code>src/TodoItem.js</code>を以下のように修正してください。</p>



<div class="hcb_wrap"><pre class="prism line-numbers lang-js" data-lang="JavaScript"><code>import React, { useState } from &#39;react&#39;;

function TodoItem({ id, text, completed, priority = &quot;medium&quot;, onToggle, onDelete, onEdit }) {
  const [isEditing, setIsEditing] = useState(false);
  const [editText, setEditText] = useState(text);

  const handleEdit = () =&gt; {
    setIsEditing(true);
    setEditText(text);
  };

  const handleSave = () =&gt; {
    if (editText.trim()) {
      onEdit(id, editText);
      setIsEditing(false);
    }
  };

  const handleCancel = () =&gt; {
    setIsEditing(false);
    setEditText(text);
  };

  const handleKeyDown = (event) =&gt; {
    if (event.key === &#39;Enter&#39;) {
      handleSave();
    }
    if (event.key === &#39;Escape&#39;) {
      handleCancel();
    }
  };

  return (
    &lt;div className={`todo-item priority-${priority}`}&gt;
      &lt;input
        type=&quot;checkbox&quot;
        checked={completed}
        onChange={() =&gt; onToggle(id)}
      /&gt;
      {isEditing ? (
        &lt;div className=&quot;edit-section&quot;&gt;
          &lt;input
            type=&quot;text&quot;
            value={editText}
            onChange={(e) =&gt; setEditText(e.target.value)}
            onKeyDown={handleKeyDown}
            className=&quot;edit-input&quot;
            autoFocus
          /&gt;
          &lt;button onClick={handleSave} className=&quot;save-button&quot;&gt;保存&lt;/button&gt;
          &lt;button onClick={handleCancel} className=&quot;cancel-button&quot;&gt;キャンセル&lt;/button&gt;
        &lt;/div&gt;
      ) : (
        &lt;div className=&quot;todo-content&quot;&gt;
          &lt;span style={{ textDecoration: completed ? &#39;line-through&#39; : &#39;none&#39; }}&gt;{text}&lt;/span&gt;
          &lt;span className={`priority-badge ${priority}`}&gt;{priority === &#39;high&#39; ? &#39;高&#39; : priority === &#39;medium&#39; ? &#39;中&#39; : &#39;低&#39;}&lt;/span&gt;
          &lt;div className=&quot;todo-actions&quot;&gt;
            &lt;button onClick={handleEdit} className=&quot;edit-button&quot;&gt;編集&lt;/button&gt;
            &lt;button onClick={() =&gt; onDelete(id)} className=&quot;delete-button&quot;&gt;削除&lt;/button&gt;
          &lt;/div&gt;
        &lt;/div&gt;
      )}
    &lt;/div&gt;
  );
}

export default TodoItem;</code></pre></div>



<h3 class="wp-block-heading">2. TodoList.jsの修正</h3>



<p>既存の<code>src/TodoList.js</code>を以下のように修正してください。</p>



<div class="hcb_wrap"><pre class="prism line-numbers lang-js" data-lang="JavaScript"><code>import React from &#39;react&#39;;
import TodoItem from &#39;./TodoItem&#39;;

function TodoList({ todos, onToggle, onDelete, onEdit }) {
  if (todos.length === 0) {
    return (
      &lt;div className=&quot;empty-state&quot;&gt;
        &lt;p&gt;TODOがありません。新しいTODOを追加してください。&lt;/p&gt;
      &lt;/div&gt;
    );
  }
  return (
    &lt;div className=&quot;todo-list&quot;&gt;
      {todos.map((todo) =&gt; (
        &lt;TodoItem
          key={todo.id}
          id={todo.id}
          text={todo.text}
          completed={todo.completed}
          priority={todo.priority}
          onToggle={onToggle}
          onDelete={onDelete}
          onEdit={onEdit}
        /&gt;
      ))}
    &lt;/div&gt;
  );
}

export default TodoList;</code></pre></div>



<h3 class="wp-block-heading">3. App.jsの修正</h3>



<p>既存の<code>src/App.js</code>を以下のように修正してください。</p>



<div class="hcb_wrap"><pre class="prism line-numbers lang-js" data-lang="JavaScript"><code>import React, { useState } from &#39;react&#39;;
import &#39;./App.css&#39;;
import TodoHeader from &#39;./TodoHeader&#39;;
import TodoList from &#39;./TodoList&#39;;
import TodoForm from &#39;./TodoForm&#39;;
import TodoFilter from &#39;./TodoFilter&#39;;

function App() {
  const [todos, setTodos] = useState([
    { id: 1, text: &quot;Reactを学ぶ&quot;, completed: false, priority: &quot;high&quot; },
    { id: 2, text: &quot;TODOアプリを作る&quot;, completed: true, priority: &quot;medium&quot; },
    { id: 3, text: &quot;データベース連携&quot;, completed: false, priority: &quot;low&quot; },
    { id: 4, text: &quot;デプロイする&quot;, completed: false, priority: &quot;medium&quot; }
  ]);
  const [filter, setFilter] = useState(&#39;all&#39;);

  const filteredTodos = todos.filter(todo =&gt; {
    if (filter === &#39;all&#39;) return true;
    if (filter === &#39;completed&#39;) return todo.completed;
    if (filter === &#39;pending&#39;) return !todo.completed;
    return true;
  });

  const completedCount = todos.filter(todo =&gt; todo.completed).length;

  const toggleTodo = (id) =&gt; {
    setTodos(prevTodos =&gt;
      prevTodos.map(todo =&gt;
        todo.id === id
          ? { ...todo, completed: !todo.completed }
          : todo
      )
    );
  };

  const addTodo = (newTodo) =&gt; {
    setTodos(prevTodos =&gt; [...prevTodos, newTodo]);
  };

  const deleteTodo = (id) =&gt; {
    setTodos(prevTodos =&gt; prevTodos.filter(todo =&gt; todo.id !== id));
  };

  const editTodo = (id, newText) =&gt; {
    setTodos(prevTodos =&gt;
      prevTodos.map(todo =&gt;
        todo.id === id
          ? { ...todo, text: newText }
          : todo
      )
    );
  };

  return (
    &lt;div className=&quot;App&quot;&gt;
      &lt;TodoHeader
        title=&quot;React TODOアプリ&quot;
        totalCount={todos.length}
        completedCount={completedCount}
      /&gt;
      &lt;TodoForm onAddTodo={addTodo} /&gt;
      &lt;TodoFilter
        filter={filter}
        onFilterChange={setFilter}
        totalCount={todos.length}
        activeCount={todos.filter(todo =&gt; !todo.completed).length}
        completedCount={completedCount}
      /&gt;
      &lt;TodoList
        todos={filteredTodos}
        onToggle={toggleTodo}
        onDelete={deleteTodo}
        onEdit={editTodo}
      /&gt;
    &lt;/div&gt;
  );
}

export default App;</code></pre></div>



<h3 class="wp-block-heading">4. App.cssの追加スタイル</h3>



<p><code>src/App.css</code>に以下のスタイルを追加してください。</p>



<div class="hcb_wrap"><pre class="prism line-numbers lang-css" data-lang="CSS"><code>.edit-section {
  display: flex;
  align-items: center;
  gap: 8px;
  flex: 1;
}
.edit-input {
  flex: 1;
  padding: 8px 12px;
  border: 2px solid #007bff;
  border-radius: 4px;
  font-size: 14px;
  outline: none;
}
.save-button {
  padding: 6px 12px;
  background-color: #28a745;
  color: white;
  border: none;
  border-radius: 4px;
  cursor: pointer;
  font-size: 12px;
}
.save-button:hover {
  background-color: #218838;
}
.cancel-button {
  padding: 6px 12px;
  background-color: #6c757d;
  color: white;
  border: none;
  border-radius: 4px;
  cursor: pointer;
  font-size: 12px;
}
.cancel-button:hover {
  background-color: #5a6268;
}
.todo-actions {
  display: flex;
  gap: 8px;
  margin-left: auto;
}
.edit-button {
  padding: 4px 8px;
  background-color: #ffc107;
  color: #212529;
  border: none;
  border-radius: 4px;
  cursor: pointer;
  font-size: 12px;
}
.edit-button:hover {
  background-color: #e0a800;
}
.delete-button {
  padding: 4px 8px;
  background-color: #dc3545;
  color: white;
  border: none;
  border-radius: 4px;
  cursor: pointer;
  font-size: 12px;
}
.delete-button:hover {
  background-color: #c82333;
}</code></pre></div>


<script async src="https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js?client=ca-pub-4374558503914683"
     crossorigin="anonymous"></script>
<!-- ディスプレイ【横長】 -->
<ins class="adsbygoogle"
     style="display:block"
     data-ad-client="ca-pub-4374558503914683"
     data-ad-slot="9744298852"
     data-ad-format="auto"
     data-full-width-responsive="true"></ins>
<script>
     (adsbygoogle = window.adsbygoogle || []).push({});
</script>



<h2 class="wp-block-heading">動作確認</h2>



<p>実装が完了したら、開発サーバーが起動している状態でブラウザを確認してください。以下の機能が動作することを確認できます。</p>


<div class="wp-block-image is-style-browser_mac size_xs">
<figure class="aligncenter size-large"><img decoding="async" width="1024" height="655" src="https://kekenta-it-blog.com/wp-content/uploads/2025/07/react_todo_series_06_01-1024x655.jpg" alt="TODOアプリ（第６回：完成イメージ）その①" class="wp-image-15513" srcset="https://kekenta-it-blog.com/wp-content/uploads/2025/07/react_todo_series_06_01-1024x655.jpg 1024w, https://kekenta-it-blog.com/wp-content/uploads/2025/07/react_todo_series_06_01-300x192.jpg 300w, https://kekenta-it-blog.com/wp-content/uploads/2025/07/react_todo_series_06_01-768x491.jpg 768w, https://kekenta-it-blog.com/wp-content/uploads/2025/07/react_todo_series_06_01.jpg 1268w" sizes="(max-width: 1024px) 100vw, 1024px" /><figcaption class="wp-element-caption">TODOアプリ（第６回：完成イメージ）その①</figcaption></figure>
</div>

<div class="wp-block-image is-style-browser_mac size_xs">
<figure class="aligncenter size-large"><img decoding="async" width="1024" height="341" src="https://kekenta-it-blog.com/wp-content/uploads/2025/07/react_todo_series_06_02-1024x341.jpg" alt="TODOアプリ（第６回：完成イメージ）その②" class="wp-image-15514" srcset="https://kekenta-it-blog.com/wp-content/uploads/2025/07/react_todo_series_06_02-1024x341.jpg 1024w, https://kekenta-it-blog.com/wp-content/uploads/2025/07/react_todo_series_06_02-300x100.jpg 300w, https://kekenta-it-blog.com/wp-content/uploads/2025/07/react_todo_series_06_02-768x256.jpg 768w, https://kekenta-it-blog.com/wp-content/uploads/2025/07/react_todo_series_06_02.jpg 1100w" sizes="(max-width: 1024px) 100vw, 1024px" /><figcaption class="wp-element-caption">TODOアプリ（第６回：完成イメージ）その②</figcaption></figure>
</div>

<div class="wp-block-image is-style-browser_mac size_xs">
<figure class="aligncenter size-large"><img decoding="async" width="1024" height="364" src="https://kekenta-it-blog.com/wp-content/uploads/2025/07/react_todo_series_06_03-1024x364.jpg" alt="TODOアプリ（第６回：完成イメージ）その③" class="wp-image-15512" srcset="https://kekenta-it-blog.com/wp-content/uploads/2025/07/react_todo_series_06_03-1024x364.jpg 1024w, https://kekenta-it-blog.com/wp-content/uploads/2025/07/react_todo_series_06_03-300x107.jpg 300w, https://kekenta-it-blog.com/wp-content/uploads/2025/07/react_todo_series_06_03-768x273.jpg 768w, https://kekenta-it-blog.com/wp-content/uploads/2025/07/react_todo_series_06_03.jpg 1047w" sizes="(max-width: 1024px) 100vw, 1024px" /><figcaption class="wp-element-caption">TODOアプリ（第６回：完成イメージ）その③</figcaption></figure>
</div>


<div class="wp-block-group is-style-big_icon_good"><div class="wp-block-group__inner-container is-layout-constrained wp-block-group-is-layout-constrained">
<ul class="wp-block-list is-style-check_list -list-under-dashed">
<li>編集ボタンで編集モードに切り替え、保存・キャンセルができる</li>



<li>削除ボタンでTODOが削除できる</li>



<li>Enterキーで保存、Escapeキーでキャンセル</li>



<li>編集・削除後もフィルタリングが正常に動作する</li>
</ul>
</div></div>



<h2 class="wp-block-heading">発展課題</h2>



<p>基本機能を理解したら、ぜひ以下の課題に挑戦してみてください！</p>



<ol class="wp-block-list">
<li><strong>削除確認ダイアログの実装</strong></li>



<li><strong>一括削除機能の追加</strong></li>



<li><strong>編集履歴の保存・元に戻す機能</strong></li>
</ol>



<h2 class="wp-block-heading">FAQ</h2>



<dl class="swell-block-faq -icon-circle is-style-faq-border" data-q="fill-custom" data-a="fill-main">
<div class="swell-block-faq__item"><dt class="faq_q">削除機能でエラーが発生する場合</dt><dd class="faq_a">
<p>onDelete関数が正しくpropsで渡されているか、filter関数の構文やIDの比較が正しいか確認してください。</p>
</dd></div>



<div class="swell-block-faq__item"><dt class="faq_q">編集機能でエラーが発生する場合</dt><dd class="faq_a">
<p>編集状態やテキストの状態管理、保存・キャンセル処理が正しく実装されているか確認してください。</p>
</dd></div>



<div class="swell-block-faq__item"><dt class="faq_q">編集モードの切り替えが動作しない場合</dt><dd class="faq_a">
<p>条件付きレンダリングの条件式や編集状態の初期値、切り替え処理が正しいか確認してください。</p>
</dd></div>



<div class="swell-block-faq__item"><dt class="faq_q">キーボードショートカットが動作しない場合</dt><dd class="faq_a">
<p>onKeyDownイベントハンドラーやキーコードの判定、イベント伝播の制御が正しいか確認してください。</p>
</dd></div>



<div class="swell-block-faq__item"><dt class="faq_q">編集後のデータが正しく更新されない場合</dt><dd class="faq_a">
<p>map関数やスプレッド演算子の使い方、状態更新関数の呼び出しが正しいか確認してください。</p>
</dd></div>



<div class="swell-block-faq__item"><dt class="faq_q">削除後のフィルタリングが正しく動作しない場合</dt><dd class="faq_a">
<p>削除後にフィルター条件が正しく適用されているか、フィルタリング関数や状態の更新タイミングが適切か確認してください。</p>
</dd></div>



<div class="swell-block-faq__item"><dt class="faq_q">編集時のバリデーションが動作しない場合</dt><dd class="faq_a">
<p>空文字チェックやバリデーション条件、エラーメッセージの表示が正しいか確認してください。</p>
</dd></div>



<div class="swell-block-faq__item"><dt class="faq_q">編集キャンセル時に元の値に戻らない場合</dt><dd class="faq_a">
<p>キャンセル処理や編集状態のリセット、初期値の保存が正しいか確認してください。</p>
</dd></div>
</dl>


<script async src="https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js?client=ca-pub-4374558503914683"
     crossorigin="anonymous"></script>
<!-- ディスプレイ【横長】 -->
<ins class="adsbygoogle"
     style="display:block"
     data-ad-client="ca-pub-4374558503914683"
     data-ad-slot="9744298852"
     data-ad-format="auto"
     data-full-width-responsive="true"></ins>
<script>
     (adsbygoogle = window.adsbygoogle || []).push({});
</script>



<h2 class="wp-block-heading">まとめ</h2>



<p>今回は、React TODOアプリに編集・削除機能を追加し、基本的なCRUD操作を完成させました。</p>



<ul class="wp-block-list is-style-check_list -list-under-dashed">
<li>filterメソッドによる削除</li>



<li>mapメソッドによる編集</li>



<li>条件付きレンダリングによる編集モードの切り替え</li>



<li>キーボードイベントの活用</li>



<li>状態管理の応用</li>
</ul>



<p>ここまでお疲れさまでした！　次回はいよいよ「基本編」の最終回です！</p>


<div class="swell-block-balloon"><div class="c-balloon -bln-left" data-col="gray"><div class="c-balloon__icon -circle"><img decoding="async" src="data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==" data-src="https://kekenta-it-blog.com/wp-content/uploads/2023/07/キリッ-150x150.jpg" alt="" class="lazyload c-balloon__iconImg" width="80px" height="80px"><noscript><img decoding="async" src="https://kekenta-it-blog.com/wp-content/uploads/2023/07/キリッ-150x150.jpg" alt="" class="c-balloon__iconImg" width="80px" height="80px"></noscript><span class="c-balloon__iconName">ケケンタ</span></div><div class="c-balloon__body -speaking -border-on"><div class="c-balloon__text">
<p>基本編の最後では、<strong>ローカルストレージを使用してデータを永続化</strong>させます。これによりブラウザを更新してもTODOリストの内容がリセットされないようになります！</p>
<span class="c-balloon__shapes"><span class="c-balloon__before"></span><span class="c-balloon__after"></span></span></div></div></div></div>


<p>データベースを使用せず簡単に実装できる内容です。ローカルストレージを使用できれば実装できることの幅が大きく広がります。次回もどうぞお楽しみに！</p>


<div class="swell-block-postLink">			<div class="p-blogCard -internal" data-type="type2" data-onclick="clickLink">
				<div class="p-blogCard__inner">
					<span class="p-blogCard__caption">次の記事</span>
					<div class="p-blogCard__thumb c-postThumb"><figure class="c-postThumb__figure"><img decoding="async" src="https://kekenta-it-blog.com/wp-content/uploads/2025/07/eye-catch__react-todo-app-useeffect-localstrage__15530-300x169.jpg" alt="" class="c-postThumb__img u-obf-cover" width="320" height="180"></figure></div>					<div class="p-blogCard__body">
						<a class="p-blogCard__title" href="https://kekenta-it-blog.com/react-todo-app-useeffect-localstrage/">【React×TODOアプリ】useEffectと副作用・ローカルストレージ【基本編：第7回】</a>
											</div>
				</div>
			</div>
		</div>

<div class="p-blogParts post_content" data-partsID="15579">
<hr class="wp-block-separator has-alpha-channel-opacity"/>



<p class="is-style-balloon_box"><span style="--the-icon-svg: url(data:image/svg+xml;base64,PHN2ZyBoZWlnaHQ9IjFlbSIgd2lkdGg9IjFlbSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiBhcmlhLWhpZGRlbj0idHJ1ZSIgdmlld0JveD0iMCAwIDQ4IDQ4Ij48cGF0aCBkPSJNMTEuNyAxLjQgNi44IDVjLS41LjQtLjggMS0uOCAxLjZ2MjguN2MwIC44LjUgMS41IDEuMiAxLjhsMjQgMTAuM2MxLjMuNiAyLjgtLjQgMi44LTEuOFYxOWMwLS44LS41LTEuNS0xLjItMS44TDEwLjIgNy41bDIuOS0yLjJjLjktLjYgMi0uOCAzLS40bDIwLjYgOC44Yy43LjMgMS4yIDEgMS4yIDEuOFY0Mi45YzAgLjkgMSAxLjMgMS43LjhsMS43LTEuNWMuNC0uNC43LS45LjctMS41VjEzYzAtLjgtLjUtMS41LTEuMi0xLjhMMTYuNy44Yy0xLjctLjctMy42LS41LTUgLjZ6Ij48L3BhdGg+PC9zdmc+)" data-icon="LsBook" data-id="0" aria-hidden="true" class="swl-inline-icon">  </span> <strong>僕が実際にReact学習に使用した書籍です</strong></p>


<div id="rinkerid15577" class="yyi-rinker-contents  yyi-rinker-postid-15577 yyi-rinker-img-m yyi-rinker-catid-256 ">
	<div class="yyi-rinker-box">
		<div class="yyi-rinker-image">
							<a href="https://www.amazon.co.jp/dp/B09BV2HGN3?tag=kekenta03am0b-22&#038;linkCode=ogi&#038;th=1&#038;psc=1" rel="nofollow" class="yyi-rinker-tracking"  data-click-tracking="amazon_img 15577 モダンJavaScriptの基本から始める　React実践の教科書　（最新ReactHooks対応）" data-vars-click-id="amazon_img 15577 モダンJavaScriptの基本から始める　React実践の教科書　（最新ReactHooks対応）"><img decoding="async" src="https://m.media-amazon.com/images/I/51Y0-P+m94L._SL160_.jpg"  width="112" height="160" class="yyi-rinker-main-img" style="border: none;"></a>					</div>
		<div class="yyi-rinker-info">
			<div class="yyi-rinker-title">
									<a href="https://www.amazon.co.jp/dp/B09BV2HGN3?tag=kekenta03am0b-22&#038;linkCode=ogi&#038;th=1&#038;psc=1" rel="nofollow" class="yyi-rinker-tracking" data-click-tracking="amazon_title 15577 モダンJavaScriptの基本から始める　React実践の教科書　（最新ReactHooks対応）" data-vars-amp-click-id="amazon_title 15577 モダンJavaScriptの基本から始める　React実践の教科書　（最新ReactHooks対応）" >モダンJavaScriptの基本から始める　React実践の教科書　（最新ReactHooks対応）</a>							</div>
			<div class="yyi-rinker-detail">
							<div class="credit-box">created by&nbsp;<a href="https://oyakosodate.com/rinker/" rel="nofollow noopener" target="_blank" >Rinker</a></div>
										<div class="price-box">
							</div>
						</div>
						<ul class="yyi-rinker-links">
																	<li class="amazonkindlelink">
						<a href="https://www.amazon.co.jp/dp/B09BV2HGN3?tag=kekenta03am0b-22&amp;linkCode=ogi&amp;th=1&amp;psc=1" rel="nofollow" class="yyi-rinker-link yyi-rinker-tracking"  data-click-tracking="amazon_kindle 15577 モダンJavaScriptの基本から始める　React実践の教科書　（最新ReactHooks対応）"  data-vars-amp-click-id="amazon_kindle 15577 モダンJavaScriptの基本から始める　React実践の教科書　（最新ReactHooks対応）">Kindle</a>					</li>
								                    <li class="amazonlink">
						<a href="https://www.amazon.co.jp/dp/B09BV2HGN3?tag=kekenta03am0b-22&amp;linkCode=ogi&amp;th=1&amp;psc=1" rel="nofollow" class="yyi-rinker-link yyi-rinker-tracking"  data-click-tracking="amazon 15577 モダンJavaScriptの基本から始める　React実践の教科書　（最新ReactHooks対応）"  data-vars-amp-click-id="amazon 15577 モダンJavaScriptの基本から始める　React実践の教科書　（最新ReactHooks対応）">Amazon</a>					</li>
													<li class="rakutenlink">
						<a href="https://hb.afl.rakuten.co.jp/hgc/3ace225e.aaf54072.3ace225f.2cf27f19/Rinker_o_20250722203529?pc=https%3A%2F%2Fsearch.rakuten.co.jp%2Fsearch%2Fmall%2F%25E3%2583%25A2%25E3%2583%2580%25E3%2583%25B3JavaScript%25E3%2581%25AE%25E5%259F%25BA%25E6%259C%25AC%25E3%2581%258B%25E3%2582%2589%25E5%25A7%258B%25E3%2582%2581%25E3%2582%258B%25E3%2580%2580React%25E5%25AE%259F%25E8%25B7%25B5%25E3%2581%25AE%25E6%2595%2599%25E7%25A7%2591%25E6%259B%25B8%25E3%2580%2580%25EF%25BC%2588%25E6%259C%2580%25E6%2596%25B0ReactHooks%25E5%25AF%25BE%25E5%25BF%259C%25EF%25BC%2589%2F%3Ff%3D1%26grp%3Dproduct&amp;m=https%3A%2F%2Fsearch.rakuten.co.jp%2Fsearch%2Fmall%2F%25E3%2583%25A2%25E3%2583%2580%25E3%2583%25B3JavaScript%25E3%2581%25AE%25E5%259F%25BA%25E6%259C%25AC%25E3%2581%258B%25E3%2582%2589%25E5%25A7%258B%25E3%2582%2581%25E3%2582%258B%25E3%2580%2580React%25E5%25AE%259F%25E8%25B7%25B5%25E3%2581%25AE%25E6%2595%2599%25E7%25A7%2591%25E6%259B%25B8%25E3%2580%2580%25EF%25BC%2588%25E6%259C%2580%25E6%2596%25B0ReactHooks%25E5%25AF%25BE%25E5%25BF%259C%25EF%25BC%2589%2F%3Ff%3D1%26grp%3Dproduct" rel="nofollow" class="yyi-rinker-link yyi-rinker-tracking"  data-click-tracking="rakuten 15577 モダンJavaScriptの基本から始める　React実践の教科書　（最新ReactHooks対応）"  data-vars-amp-click-id="rakuten 15577 モダンJavaScriptの基本から始める　React実践の教科書　（最新ReactHooks対応）">楽天市場</a>					</li>
								                											</ul>
					</div>
	</div>
</div>
</div>
]]></content:encoded>
					
					<wfw:commentRss>https://kekenta-it-blog.com/react-todo-app-edit-delete-crud/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>【React×TODOアプリ】リスト表示と条件付きレンダリング【基本編：第5回】</title>
		<link>https://kekenta-it-blog.com/react-list-display-conditional-rendering/</link>
					<comments>https://kekenta-it-blog.com/react-list-display-conditional-rendering/#respond</comments>
		
		<dc:creator><![CDATA[ケケンタ]]></dc:creator>
		<pubDate>Mon, 21 Jul 2025 21:26:24 +0000</pubDate>
				<category><![CDATA[React]]></category>
		<category><![CDATA[Javascript]]></category>
		<category><![CDATA[TODOアプリ]]></category>
		<category><![CDATA[開発シリーズ]]></category>
		<guid isPermaLink="false">https://kekenta-it-blog.com/?p=15497</guid>

					<description><![CDATA[<p><img src="https://kekenta-it-blog.com/wp-content/uploads/2025/07/eye-catch__react-list-display-conditional-rendering__15497-1024x576.jpg" class="webfeedsFeaturedVisual" /></p>Reactで作るTODOアプリ開発シリーズ第５回 この記事では Reactでのリスト表示と条件付きレンダリングの実装方法 を学習していきます。 前回はイベントハンドリングとフォーム処理について学習しました。今回は、データ [&#8230;]]]></description>
										<content:encoded><![CDATA[<p><img src="https://kekenta-it-blog.com/wp-content/uploads/2025/07/eye-catch__react-list-display-conditional-rendering__15497-1024x576.jpg" class="webfeedsFeaturedVisual" /></p>
<p><strong>Reactで作るTODOアプリ開発シリーズ第５回</strong></p>



<p>この記事では</p>



<p class="has-text-align-center is-style-big_kakko_box"><strong>Reactでのリスト表示と条件付きレンダリングの実装方法</strong></p>



<p>を学習していきます。</p>


<div class="swell-block-postLink">			<div class="p-blogCard -internal" data-type="type2" data-onclick="clickLink">
				<div class="p-blogCard__inner">
					<span class="p-blogCard__caption">前回の記事</span>
					<div class="p-blogCard__thumb c-postThumb"><figure class="c-postThumb__figure"><img decoding="async" src="https://kekenta-it-blog.com/wp-content/uploads/2025/07/eye-catch__react-event-handling-form-processing__15483-300x169.jpg" alt="" class="c-postThumb__img u-obf-cover" width="320" height="180"></figure></div>					<div class="p-blogCard__body">
						<a class="p-blogCard__title" href="https://kekenta-it-blog.com/react-event-handling-form-processing/">【React×TODOアプリ】イベントハンドリングとフォーム処理【基本編：第4回】</a>
											</div>
				</div>
			</div>
		</div>


<p><a href="https://kekenta-it-blog.com/react-event-handling-form-processing/">前回</a>は<strong>イベントハンドリングとフォーム処理</strong>について学習しました。今回は、データを動的に表示し、条件に応じてUIを制御する方法について学んでいきましょう。</p>



<p>リスト表示と条件付きレンダリングは、Reactアプリケーションで最もよく使われる機能の一つです。これらを適切に実装することで、ユーザーにとって使いやすく、見た目も美しいアプリケーションを作ることができます。</p>



<div class="swell-block-capbox cap_box"><div class="cap_box_ttl"><span><span data-icon="LsLightbulb" data-id="0" style="--the-icon-svg: url(data:image/svg+xml;base64,PHN2ZyBoZWlnaHQ9IjFlbSIgd2lkdGg9IjFlbSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiBhcmlhLWhpZGRlbj0idHJ1ZSIgdmlld0JveD0iMCAwIDQ4IDQ4Ij48cGF0aCBkPSJNMzIgNDYuNUgxNmMtMS4xIDAtMi0uOS0yLTJzLjktMiAyLTJoMTZjMS4xIDAgMiAuOSAyIDJzLS45IDItMiAyek00MS43IDE1LjlDNDEuMyAxMyA0MCAxMC4zIDM4LjIgOCAzNC41IDMuMiAyOSAuOCAyMy4xIDEgMTQgMS40IDYuNSA4LjkgNiAxOGMtLjMgNiAyLjQgMTEuNyA3LjIgMTUuNC41LjQuOC45LjggMS41djEuNmMwIDIuMiAxLjggNCA0IDRoMTJjMi4yIDAgNC0xLjggNC00VjM1YzAtLjYuMy0xLjIuOS0xLjcgNS4zLTQgOC0xMC42IDYuOC0xNy40em0tNy4xIDEuN2gtLjNjLS43IDAtMS4zLS41LTEuNS0xLjItLjctMy4yLTMuMi01LjctNi40LTYuMy0uOC0uMS0xLjQtLjktMS4yLTEuN3MuOS0xLjQgMS43LTEuMmM0LjQuOCA4IDQuMiA4LjkgOC42LjEuOC0uNCAxLjYtMS4yIDEuOHoiPjwvcGF0aD48L3N2Zz4=)" aria-hidden="true" class="swl-inline-icon"> </span> <strong>この記事でわかること</strong></span></div><div class="cap_box_content">
<ul class="wp-block-list is-style-check_list -list-under-dashed">
<li>map関数を使ったリスト表示の基本</li>



<li>keyプロパティの重要性と使い方</li>



<li>条件付きレンダリング（&amp;&amp;演算子、三項演算子）</li>



<li>TODOリストの表示とフィルタリング</li>



<li>完了/未完了の切り替え表示</li>
</ul>
</div></div>


<div class="swell-block-balloon"><div class="c-balloon -bln-left" data-col="gray"><div class="c-balloon__icon -circle"><img decoding="async" src="data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==" data-src="https://kekenta-it-blog.com/wp-content/uploads/2023/07/キリッ-150x150.jpg" alt="" class="lazyload c-balloon__iconImg" width="80px" height="80px"><noscript><img decoding="async" src="https://kekenta-it-blog.com/wp-content/uploads/2023/07/キリッ-150x150.jpg" alt="" class="c-balloon__iconImg" width="80px" height="80px"></noscript><span class="c-balloon__iconName">ケケンタ</span></div><div class="c-balloon__body -speaking -border-on"><div class="c-balloon__text">
<p>リスト表示と条件付きレンダリングを理解することで、データに応じて動的に変化するUIを作ることができるようになります！</p>
<span class="c-balloon__shapes"><span class="c-balloon__before"></span><span class="c-balloon__after"></span></span></div></div></div></div>

<div class="wp-block-image is-style-browser_mac size_xs">
<figure class="aligncenter size-full"><img decoding="async" width="1198" height="807" src="https://kekenta-it-blog.com/wp-content/uploads/2025/07/react_todo_series_05_01.jpg" alt="TODOアプリ（第５回：完成イメージ）その①" class="wp-image-15500" srcset="https://kekenta-it-blog.com/wp-content/uploads/2025/07/react_todo_series_05_01.jpg 1198w, https://kekenta-it-blog.com/wp-content/uploads/2025/07/react_todo_series_05_01-300x202.jpg 300w, https://kekenta-it-blog.com/wp-content/uploads/2025/07/react_todo_series_05_01-1024x690.jpg 1024w, https://kekenta-it-blog.com/wp-content/uploads/2025/07/react_todo_series_05_01-768x517.jpg 768w" sizes="(max-width: 1198px) 100vw, 1198px" /><figcaption class="wp-element-caption">TODOアプリ（第５回：完成イメージ）その①</figcaption></figure>
</div>

<div class="wp-block-image is-style-browser_mac size_xs">
<figure class="aligncenter size-full"><img decoding="async" width="1019" height="351" src="https://kekenta-it-blog.com/wp-content/uploads/2025/07/react_todo_series_05_02.jpg" alt="TODOアプリ（第５回：完成イメージ）その②" class="wp-image-15501" srcset="https://kekenta-it-blog.com/wp-content/uploads/2025/07/react_todo_series_05_02.jpg 1019w, https://kekenta-it-blog.com/wp-content/uploads/2025/07/react_todo_series_05_02-300x103.jpg 300w, https://kekenta-it-blog.com/wp-content/uploads/2025/07/react_todo_series_05_02-768x265.jpg 768w" sizes="(max-width: 1019px) 100vw, 1019px" /><figcaption class="wp-element-caption">TODOアプリ（第５回：完成イメージ）その②</figcaption></figure>
</div>

<div class="wp-block-image is-style-browser_mac size_xs">
<figure class="aligncenter size-full"><img decoding="async" width="995" height="235" src="https://kekenta-it-blog.com/wp-content/uploads/2025/07/react_todo_series_05_03.jpg" alt="TODOアプリ（第５回：完成イメージ）その③" class="wp-image-15502" srcset="https://kekenta-it-blog.com/wp-content/uploads/2025/07/react_todo_series_05_03.jpg 995w, https://kekenta-it-blog.com/wp-content/uploads/2025/07/react_todo_series_05_03-300x71.jpg 300w, https://kekenta-it-blog.com/wp-content/uploads/2025/07/react_todo_series_05_03-768x181.jpg 768w" sizes="(max-width: 995px) 100vw, 995px" /><figcaption class="wp-element-caption">TODOアプリ（第５回：完成イメージ）その③</figcaption></figure>
</div>

<div class="wp-block-image is-style-browser_mac size_xs">
<figure class="aligncenter size-full"><img decoding="async" width="951" height="303" src="https://kekenta-it-blog.com/wp-content/uploads/2025/07/react_todo_series_05_04.jpg" alt="TODOアプリ（第５回：完成イメージ）その④" class="wp-image-15499" srcset="https://kekenta-it-blog.com/wp-content/uploads/2025/07/react_todo_series_05_04.jpg 951w, https://kekenta-it-blog.com/wp-content/uploads/2025/07/react_todo_series_05_04-300x96.jpg 300w, https://kekenta-it-blog.com/wp-content/uploads/2025/07/react_todo_series_05_04-768x245.jpg 768w" sizes="(max-width: 951px) 100vw, 951px" /><figcaption class="wp-element-caption">TODOアプリ（第５回：完成イメージ）その④</figcaption></figure>
</div>


<p class="is-style-balloon_box"><span style="--the-icon-svg: url(data:image/svg+xml;base64,PHN2ZyBoZWlnaHQ9IjFlbSIgd2lkdGg9IjFlbSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiBhcmlhLWhpZGRlbj0idHJ1ZSIgdmlld0JveD0iMCAwIDQ4IDQ4Ij48cGF0aCBkPSJNMTAgM2gyOGMxLjEgMCAyIC45IDIgMnYzOS42YzAgLjktMS4xIDEuMy0xLjcuN0wyNCAzMSA5LjcgNDUuM2MtLjYuNi0xLjcuMi0xLjctLjdWNWMwLTEuMS45LTIgMi0yeiI+PC9wYXRoPjwvc3ZnPg==)" data-icon="LsBookmark" data-id="0" aria-hidden="true" class="swl-inline-icon"> </span> <strong>TODOアプリ開発シリーズのまとめ記事はこちら</strong></p>


<div class="swell-block-postLink">			<div class="p-blogCard -internal" data-type="type2" data-onclick="clickLink">
				<div class="p-blogCard__inner">
					<span class="p-blogCard__caption">シリーズ完全ガイド</span>
					<div class="p-blogCard__thumb c-postThumb"><figure class="c-postThumb__figure"><img decoding="async" src="https://kekenta-it-blog.com/wp-content/uploads/2025/07/eye-catch__react-todo-app-series-complete-guide-summary__15557-300x169.jpg" alt="" class="c-postThumb__img u-obf-cover" width="320" height="180"></figure></div>					<div class="p-blogCard__body">
						<a class="p-blogCard__title" href="https://kekenta-it-blog.com/react-todo-app-series-complete-guide-summary/">【React】初心者向けTODOアプリ開発シリーズ &#8211; 完全ガイドまとめ</a>
											</div>
				</div>
			</div>
		</div>


<h2 class="wp-block-heading">前回までのコード</h2>



<p>第4回で作成したコードを確認しましょう。以下のファイル構成になっています。</p>



<h3 class="wp-block-heading">ファイル構造</h3>



<div class="hcb_wrap"><pre class="prism line-numbers lang-plain"><code>todo-app/
├── src/
│   ├── App.js
│   ├── App.css
│   ├── TodoItem.js
│   ├── TodoList.js
│   ├── TodoHeader.js
│   └── TodoForm.js</code></pre></div>



<h3 class="wp-block-heading">App.js</h3>



<div class="hcb_wrap"><pre class="prism line-numbers lang-js" data-lang="JavaScript"><code>import React, { useState } from &#39;react&#39;;
import &#39;./App.css&#39;;
import TodoHeader from &#39;./TodoHeader&#39;;
import TodoList from &#39;./TodoList&#39;;
import TodoForm from &#39;./TodoForm&#39;;

function App() {
  const [todos, setTodos] = useState([
    { id: 1, text: &quot;Reactを学ぶ&quot;, completed: false, priority: &quot;high&quot; },
    { id: 2, text: &quot;TODOアプリを作る&quot;, completed: true, priority: &quot;medium&quot; },
    { id: 3, text: &quot;データベース連携&quot;, completed: false, priority: &quot;low&quot; },
    { id: 4, text: &quot;デプロイする&quot;, completed: false, priority: &quot;medium&quot; }
  ]);

  const completedCount = todos.filter(todo =&gt; todo.completed).length;

  // TODOの完了状態を切り替える関数
  const toggleTodo = (id) =&gt; {
    setTodos(prevTodos =&gt; 
      prevTodos.map(todo =&gt; 
        todo.id === id 
          ? { ...todo, completed: !todo.completed }
          : todo
      )
    );
  };

  // 新しいTODOを追加する関数
  const addTodo = (newTodo) =&gt; {
    setTodos(prevTodos =&gt; [...prevTodos, newTodo]);
  };

  return (
    &lt;div className=&quot;App&quot;&gt;
      &lt;TodoHeader 
        title=&quot;React TODOアプリ&quot;
        totalCount={todos.length}
        completedCount={completedCount}
      /&gt;
      &lt;TodoForm onAddTodo={addTodo} /&gt;
      &lt;TodoList todos={todos} onToggle={toggleTodo} /&gt;
    &lt;/div&gt;
  );
}

export default App;</code></pre></div>



<h3 class="wp-block-heading">TodoForm.js</h3>



<div class="hcb_wrap"><pre class="prism line-numbers lang-js" data-lang="JavaScript"><code>import React, { useState } from &#39;react&#39;;

function TodoForm({ onAddTodo }) {
  const [formData, setFormData] = useState({
    text: &#39;&#39;,
    priority: &#39;medium&#39;
  });
  const [error, setError] = useState(&#39;&#39;);

  const handleChange = (event) =&gt; {
    const { name, value } = event.target;
    setFormData(prevData =&gt; ({
      ...prevData,
      [name]: value
    }));

    if (error) {
      setError(&#39;&#39;);
    }
  };

  const handleSubmit = (event) =&gt; {
    event.preventDefault();

    if (!formData.text.trim()) {
      setError(&#39;TODOの内容を入力してください&#39;);
      return;
    }

    if (formData.text.length &gt; 100) {
      setError(&#39;TODOの内容は100文字以下で入力してください&#39;);
      return;
    }

    const newTodo = {
      id: Date.now(),
      text: formData.text.trim(),
      completed: false,
      priority: formData.priority
    };

    onAddTodo(newTodo);

    setFormData({
      text: &#39;&#39;,
      priority: &#39;medium&#39;
    });
    setError(&#39;&#39;);
  };

  return (
    &lt;form onSubmit={handleSubmit} className=&quot;todo-form&quot;&gt;
      &lt;div className=&quot;form-group&quot;&gt;
        &lt;input
          type=&quot;text&quot;
          name=&quot;text&quot;
          value={formData.text}
          onChange={handleChange}
          placeholder=&quot;新しいTODOを入力してください&quot;
          className=&quot;todo-input&quot;
        /&gt;
        &lt;select
          name=&quot;priority&quot;
          value={formData.priority}
          onChange={handleChange}
          className=&quot;priority-select&quot;
        &gt;
          &lt;option value=&quot;low&quot;&gt;低優先度&lt;/option&gt;
          &lt;option value=&quot;medium&quot;&gt;中優先度&lt;/option&gt;
          &lt;option value=&quot;high&quot;&gt;高優先度&lt;/option&gt;
        &lt;/select&gt;
        &lt;button type=&quot;submit&quot; className=&quot;add-button&quot;&gt;
          追加
        &lt;/button&gt;
      &lt;/div&gt;
      {error && &lt;p className=&quot;error-message&quot;&gt;{error}&lt;/p&gt;}
    &lt;/form&gt;
  );
}

export default TodoForm;</code></pre></div>



<h3 class="wp-block-heading">App.css</h3>



<div class="hcb_wrap"><pre class="prism line-numbers lang-css" data-lang="CSS"><code>.todo-form {
  margin-bottom: 30px;
  padding: 20px;
  background-color: #f8f9fa;
  border-radius: 8px;
}

.form-group {
  display: flex;
  gap: 10px;
  align-items: center;
}

.todo-input {
  flex: 1;
  padding: 10px;
  border: 1px solid #ddd;
  border-radius: 4px;
  font-size: 16px;
}

.todo-input:focus {
  outline: none;
  border-color: #007bff;
  box-shadow: 0 0 0 2px rgba(0, 123, 255, 0.25);
}

.priority-select {
  padding: 10px;
  border: 1px solid #ddd;
  border-radius: 4px;
  font-size: 16px;
  background-color: white;
}

.add-button {
  padding: 10px 20px;
  background-color: #007bff;
  color: white;
  border: none;
  border-radius: 4px;
  font-size: 16px;
  cursor: pointer;
  transition: background-color 0.2s;
}

.add-button:hover {
  background-color: #0056b3;
}

.add-button:disabled {
  background-color: #6c757d;
  cursor: not-allowed;
}

.error-message {
  color: #dc3545;
  margin-top: 10px;
  font-size: 14px;
}</code></pre></div>


<script async src="https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js?client=ca-pub-4374558503914683"
     crossorigin="anonymous"></script>
<!-- ディスプレイ【横長】 -->
<ins class="adsbygoogle"
     style="display:block"
     data-ad-client="ca-pub-4374558503914683"
     data-ad-slot="9744298852"
     data-ad-format="auto"
     data-full-width-responsive="true"></ins>
<script>
     (adsbygoogle = window.adsbygoogle || []).push({});
</script>



<h2 class="wp-block-heading">リスト表示の基本</h2>



<p class="is-style-bg_stripe">実際に手を動かす前に、まずは必要な知識について解説をしていきます。</p>



<p>Reactで配列のデータを表示するには、<code>map</code>関数を使用します。<code>map</code>関数は、配列の各要素に対して処理を行い、新しい配列を返します。</p>



<h3 class="wp-block-heading">基本的なリスト表示</h3>



<div class="hcb_wrap"><pre class="prism line-numbers lang-js" data-lang="JavaScript"><code>function BasicList() {
  const items = [&quot;りんご&quot;, &quot;みかん&quot;, &quot;バナナ&quot;, &quot;ぶどう&quot;];

  return (
    &lt;div&gt;
      &lt;h3&gt;果物リスト&lt;/h3&gt;
      &lt;ul&gt;
        {items.map((item, index) =&gt; (
          &lt;li key={index}&gt;{item}&lt;/li&gt;
        ))}
      &lt;/ul&gt;
    &lt;/div&gt;
  );
}</code></pre></div>



<h3 class="wp-block-heading">オブジェクトのリスト表示</h3>



<div class="hcb_wrap"><pre class="prism line-numbers lang-js" data-lang="JavaScript"><code>function ObjectList() {
  const users = [
    { id: 1, name: &quot;田中太郎&quot;, age: 25 },
    { id: 2, name: &quot;佐藤花子&quot;, age: 30 },
    { id: 3, name: &quot;鈴木一郎&quot;, age: 28 }
  ];

  return (
    &lt;div&gt;
      &lt;h3&gt;ユーザーリスト&lt;/h3&gt;
      &lt;ul&gt;
        {users.map(user =&gt; (
          &lt;li key={user.id}&gt;
            {user.name} ({user.age}歳)
          &lt;/li&gt;
        ))}
      &lt;/ul&gt;
    &lt;/div&gt;
  );
}</code></pre></div>



<h2 class="wp-block-heading">keyプロパティの重要性</h2>



<p>Reactでリストを表示する際、各要素に一意の<code>key</code>プロパティを指定する必要があります。これは、Reactが要素を効率的に更新するために使用されます。</p>



<h3 class="wp-block-heading">keyプロパティの基本</h3>



<div class="hcb_wrap"><pre class="prism line-numbers lang-js" data-lang="JavaScript"><code>function KeyExample() {
  const [items, setItems] = useState([
    { id: 1, text: &quot;アイテム1&quot; },
    { id: 2, text: &quot;アイテム2&quot; },
    { id: 3, text: &quot;アイテム3&quot; }
  ]);

  const addItem = () =&gt; {
    const newItem = {
      id: Date.now(),
      text: `アイテム${items.length + 1}`
    };
    setItems(prevItems =&gt; [...prevItems, newItem]);
  };

  return (
    &lt;div&gt;
      &lt;button onClick={addItem}&gt;アイテムを追加&lt;/button&gt;
      &lt;ul&gt;
        {items.map(item =&gt; (
          &lt;li key={item.id}&gt;{item.text}&lt;/li&gt;
        ))}
      &lt;/ul&gt;
    &lt;/div&gt;
  );
}</code></pre></div>



<h3 class="wp-block-heading">keyプロパティの注意点</h3>



<div class="hcb_wrap"><pre class="prism line-numbers lang-js" data-lang="JavaScript"><code>// ❌ 避けるべき書き方（indexをkeyとして使用）
function BadKeyExample() {
  const items = [&quot;りんご&quot;, &quot;みかん&quot;, &quot;バナナ&quot;];

  return (
    &lt;ul&gt;
      {items.map((item, index) =&gt; (
        &lt;li key={index}&gt;{item}&lt;/li&gt; // 配列の順序が変わる可能性がある場合は危険
      ))}
    &lt;/ul&gt;
  );
}

// ✅ 推奨される書き方（一意のIDを使用）
function GoodKeyExample() {
  const items = [
    { id: 1, name: &quot;りんご&quot; },
    { id: 2, name: &quot;みかん&quot; },
    { id: 3, name: &quot;バナナ&quot; }
  ];

  return (
    &lt;ul&gt;
      {items.map(item =&gt; (
        &lt;li key={item.id}&gt;{item.name}&lt;/li&gt;
      ))}
    &lt;/ul&gt;
  );
}</code></pre></div>


<script async src="https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js?client=ca-pub-4374558503914683"
     crossorigin="anonymous"></script>
<!-- ディスプレイ【横長】 -->
<ins class="adsbygoogle"
     style="display:block"
     data-ad-client="ca-pub-4374558503914683"
     data-ad-slot="9744298852"
     data-ad-format="auto"
     data-full-width-responsive="true"></ins>
<script>
     (adsbygoogle = window.adsbygoogle || []).push({});
</script>



<h2 class="wp-block-heading">条件付きレンダリング</h2>



<p>条件付きレンダリングは、特定の条件に基づいて異なるコンテンツを表示する機能です。</p>



<h3 class="wp-block-heading">基本的な条件付きレンダリング</h3>



<h4 class="wp-block-heading">1. &amp;&amp;演算子を使用</h4>



<div class="hcb_wrap"><pre class="prism line-numbers lang-js" data-lang="JavaScript"><code>function ConditionalRendering() {
  const [isLoggedIn, setIsLoggedIn] = useState(false);
  const [userName, setUserName] = useState(&quot;&quot;);

  return (
    &lt;div&gt;
      {isLoggedIn && (
        &lt;div&gt;
          &lt;h2&gt;ようこそ、{userName}さん！&lt;/h2&gt;
          &lt;button onClick={() =&gt; setIsLoggedIn(false)}&gt;
            ログアウト
          &lt;/button&gt;
        &lt;/div&gt;
      )}

      {!isLoggedIn && (
        &lt;div&gt;
          &lt;h2&gt;ログインしてください&lt;/h2&gt;
          &lt;input
            type=&quot;text&quot;
            placeholder=&quot;ユーザー名&quot;
            value={userName}
            onChange={(e) =&gt; setUserName(e.target.value)}
          /&gt;
          &lt;button onClick={() =&gt; setIsLoggedIn(true)}&gt;
            ログイン
          &lt;/button&gt;
        &lt;/div&gt;
      )}
    &lt;/div&gt;
  );
}</code></pre></div>



<h4 class="wp-block-heading">2. 三項演算子を使用</h4>



<div class="hcb_wrap"><pre class="prism line-numbers lang-js" data-lang="JavaScript"><code>function TernaryExample() {
  const [isLoading, setIsLoading] = useState(true);
  const [data, setData] = useState(null);

  return (
    &lt;div&gt;
      {isLoading ? (
        &lt;div&gt;読み込み中...&lt;/div&gt;
      ) : (
        &lt;div&gt;
          &lt;h3&gt;データが読み込まれました&lt;/h3&gt;
          &lt;p&gt;{data}&lt;/p&gt;
        &lt;/div&gt;
      )}
    &lt;/div&gt;
  );
}</code></pre></div>



<h4 class="wp-block-heading">3. 複数の条件分岐</h4>



<div class="hcb_wrap"><pre class="prism line-numbers lang-js" data-lang="JavaScript"><code>function MultipleConditions() {
  const [status, setStatus] = useState(&quot;loading&quot;);

  const renderContent = () =&gt; {
    switch (status) {
      case &quot;loading&quot;:
        return &lt;div&gt;読み込み中...&lt;/div&gt;;
      case &quot;success&quot;:
        return &lt;div&gt;成功しました！&lt;/div&gt;;
      case &quot;error&quot;:
        return &lt;div&gt;エラーが発生しました&lt;/div&gt;;
      default:
        return &lt;div&gt;不明な状態です&lt;/div&gt;;
    }
  };

  return (
    &lt;div&gt;
      &lt;div&gt;現在の状態: {status}&lt;/div&gt;
      {renderContent()}
      &lt;button onClick={() =&gt; setStatus(&quot;success&quot;)}&gt;
        成功にする
      &lt;/button&gt;
      &lt;button onClick={() =&gt; setStatus(&quot;error&quot;)}&gt;
        エラーにする
      &lt;/button&gt;
    &lt;/div&gt;
  );
}</code></pre></div>



<h2 class="wp-block-heading">リスト表示と条件付きレンダリングの組み合わせ</h2>



<p>実際のアプリケーションでは、リスト表示と条件付きレンダリングを組み合わせて使用することが多いです。</p>



<h3 class="wp-block-heading">フィルタリング機能の実装</h3>



<div class="hcb_wrap"><pre class="prism line-numbers lang-js" data-lang="JavaScript"><code>function FilteredList() {
  const [filter, setFilter] = useState(&quot;all&quot;);
  const [items, setItems] = useState([
    { id: 1, text: &quot;買い物に行く&quot;, completed: false },
    { id: 2, text: &quot;本を読む&quot;, completed: true },
    { id: 3, text: &quot;運動する&quot;, completed: false },
    { id: 4, text: &quot;料理を作る&quot;, completed: true }
  ]);

  const filteredItems = items.filter(item =&gt; {
    if (filter === &quot;all&quot;) return true;
    if (filter === &quot;completed&quot;) return item.completed;
    if (filter === &quot;pending&quot;) return !item.completed;
    return true;
  });

  return (
    &lt;div&gt;
      &lt;div&gt;
        &lt;button onClick={() =&gt; setFilter(&quot;all&quot;)}&gt;
          すべて
        &lt;/button&gt;
        &lt;button onClick={() =&gt; setFilter(&quot;completed&quot;)}&gt;
          完了済み
        &lt;/button&gt;
        &lt;button onClick={() =&gt; setFilter(&quot;pending&quot;)}&gt;
          未完了
        &lt;/button&gt;
      &lt;/div&gt;

      &lt;ul&gt;
        {filteredItems.map(item =&gt; (
          &lt;li key={item.id}&gt;
            &lt;span style={{ 
              textDecoration: item.completed ? &#39;line-through&#39; : &#39;none&#39; 
            }}&gt;
              {item.text}
            &lt;/span&gt;
            {item.completed && &lt;span&gt; ✓&lt;/span&gt;}
          &lt;/li&gt;
        ))}
      &lt;/ul&gt;

      {filteredItems.length === 0 && (
        &lt;p&gt;該当するアイテムがありません&lt;/p&gt;
      )}
    &lt;/div&gt;
  );
}</code></pre></div>


<script async src="https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js?client=ca-pub-4374558503914683"
     crossorigin="anonymous"></script>
<!-- ディスプレイ【横長】 -->
<ins class="adsbygoogle"
     style="display:block"
     data-ad-client="ca-pub-4374558503914683"
     data-ad-slot="9744298852"
     data-ad-format="auto"
     data-full-width-responsive="true"></ins>
<script>
     (adsbygoogle = window.adsbygoogle || []).push({});
</script>



<h2 class="wp-block-heading">【実践】フィルタリング機能と条件付きレンダリングの実装</h2>



<p class="is-style-bg_stripe">ここからは実際に手を動かして、TODOアプリに<strong>フィルタリング機能と条件付きレンダリング</strong>を追加していきましょう。</p>



<h3 class="wp-block-heading">1. TodoFilterコンポーネントの作成</h3>



<p><code>src/TodoFilter.js</code>ファイルを新規作成し、以下のコードを記述してください。</p>



<div class="hcb_wrap"><pre class="prism line-numbers lang-js" data-lang="JavaScript"><code>import React from &#39;react&#39;;

function TodoFilter({ filter, onFilterChange }) {
  return (
    &lt;div className=&quot;todo-filter&quot;&gt;
      &lt;button
        className={`filter-button ${filter === &#39;all&#39; ? &#39;active&#39; : &#39;&#39;}`}
        onClick={() =&gt; onFilterChange(&#39;all&#39;)}
      &gt;
        すべて
      &lt;/button&gt;
      &lt;button
        className={`filter-button ${filter === &#39;pending&#39; ? &#39;active&#39; : &#39;&#39;}`}
        onClick={() =&gt; onFilterChange(&#39;pending&#39;)}
      &gt;
        未完了
      &lt;/button&gt;
      &lt;button
        className={`filter-button ${filter === &#39;completed&#39; ? &#39;active&#39; : &#39;&#39;}`}
        onClick={() =&gt; onFilterChange(&#39;completed&#39;)}
      &gt;
        完了済み
      &lt;/button&gt;
    &lt;/div&gt;
  );
}

export default TodoFilter;</code></pre></div>



<h3 class="wp-block-heading">2. App.jsの修正</h3>



<p>既存の<code>src/App.js</code>を以下のように修正してください。</p>



<div class="hcb_wrap"><pre class="prism line-numbers lang-js" data-lang="JavaScript"><code>import React, { useState } from &#39;react&#39;;
import &#39;./App.css&#39;;
import TodoHeader from &#39;./TodoHeader&#39;;
import TodoList from &#39;./TodoList&#39;;
import TodoForm from &#39;./TodoForm&#39;;
import TodoFilter from &#39;./TodoFilter&#39;;

function App() {
  const [todos, setTodos] = useState([
    { id: 1, text: &quot;Reactを学ぶ&quot;, completed: false, priority: &quot;high&quot; },
    { id: 2, text: &quot;TODOアプリを作る&quot;, completed: true, priority: &quot;medium&quot; },
    { id: 3, text: &quot;データベース連携&quot;, completed: false, priority: &quot;low&quot; },
    { id: 4, text: &quot;デプロイする&quot;, completed: false, priority: &quot;medium&quot; }
  ]);

  const [filter, setFilter] = useState(&#39;all&#39;);

  // フィルタリングされたTODOリスト
  const filteredTodos = todos.filter(todo =&gt; {
    if (filter === &#39;all&#39;) return true;
    if (filter === &#39;completed&#39;) return todo.completed;
    if (filter === &#39;pending&#39;) return !todo.completed;
    return true;
  });

  const completedCount = todos.filter(todo =&gt; todo.completed).length;

  // TODOの完了状態を切り替える関数
  const toggleTodo = (id) =&gt; {
    setTodos(prevTodos =&gt; 
      prevTodos.map(todo =&gt; 
        todo.id === id 
          ? { ...todo, completed: !todo.completed }
          : todo
      )
    );
  };

  // 新しいTODOを追加する関数
  const addTodo = (newTodo) =&gt; {
    setTodos(prevTodos =&gt; [...prevTodos, newTodo]);
  };

  return (
    &lt;div className=&quot;App&quot;&gt;
      &lt;TodoHeader 
        title=&quot;React TODOアプリ&quot;
        totalCount={todos.length}
        completedCount={completedCount}
      /&gt;
      &lt;TodoForm onAddTodo={addTodo} /&gt;
      &lt;TodoFilter filter={filter} onFilterChange={setFilter} /&gt;
      &lt;TodoList todos={filteredTodos} onToggle={toggleTodo} /&gt;
    &lt;/div&gt;
  );
}

export default App;</code></pre></div>



<h3 class="wp-block-heading">3. TodoList.jsの修正</h3>



<p>既存の<code>src/TodoList.js</code>を以下のように修正してください。</p>



<div class="hcb_wrap"><pre class="prism line-numbers lang-js" data-lang="JavaScript"><code>import React from &#39;react&#39;;
import TodoItem from &#39;./TodoItem&#39;;

function TodoList({ todos, onToggle }) {
  // TODOが存在しない場合の表示
  if (todos.length === 0) {
    return (
      &lt;div className=&quot;empty-state&quot;&gt;
        &lt;p&gt;TODOがありません。新しいTODOを追加してください。&lt;/p&gt;
      &lt;/div&gt;
    );
  }

  return (
    &lt;div className=&quot;todo-list&quot;&gt;
      {todos.map((todo) =&gt; (
        &lt;TodoItem 
          key={todo.id}
          id={todo.id}
          text={todo.text}
          completed={todo.completed}
          priority={todo.priority}
          onToggle={onToggle}
        /&gt;
      ))}
    &lt;/div&gt;
  );
}

export default TodoList;</code></pre></div>



<h3 class="wp-block-heading">4. TodoItem.jsの修正</h3>



<p>既存の<code>src/TodoItem.js</code>を以下のように修正してください。</p>



<div class="hcb_wrap"><pre class="prism line-numbers lang-js" data-lang="JavaScript"><code>import React from &#39;react&#39;;

function TodoItem({ id, text, completed, priority = &quot;medium&quot;, onToggle }) {
  return (
    &lt;div className={`todo-item priority-${priority}`}&gt;
      &lt;input 
        type=&quot;checkbox&quot; 
        checked={completed} 
        onChange={() =&gt; onToggle(id)}
      /&gt;
      &lt;span style={{ 
        textDecoration: completed ? &#39;line-through&#39; : &#39;none&#39; 
      }}&gt;
        {text}
      &lt;/span&gt;
      {completed && (
        &lt;span className=&quot;completed-badge&quot;&gt;完了&lt;/span&gt;
      )}
      {!completed && (
        &lt;span className=&quot;pending-badge&quot;&gt;未完了&lt;/span&gt;
      )}
    &lt;/div&gt;
  );
}

export default TodoItem;</code></pre></div>



<h3 class="wp-block-heading">5. スタイルの追加</h3>



<p>既存の<code>src/App.css</code>に以下のスタイルを追加してください。</p>



<div class="hcb_wrap"><pre class="prism line-numbers lang-css" data-lang="CSS"><code>.todo-filter {
  display: flex;
  justify-content: center;
  gap: 10px;
  margin-bottom: 20px;
}

.filter-button {
  padding: 8px 16px;
  border: 1px solid #ddd;
  background-color: white;
  border-radius: 4px;
  cursor: pointer;
  transition: all 0.2s;
}

.filter-button:hover {
  background-color: #f8f9fa;
}

.filter-button.active {
  background-color: #007bff;
  color: white;
  border-color: #007bff;
}

.empty-state {
  text-align: center;
  padding: 40px;
  color: #666;
  font-style: italic;
}

.completed-badge {
  background-color: #28a745;
  color: white;
  padding: 2px 8px;
  border-radius: 12px;
  font-size: 12px;
  margin-left: 10px;
}

.pending-badge {
  background-color: #ffc107;
  color: #212529;
  padding: 2px 8px;
  border-radius: 12px;
  font-size: 12px;
  margin-left: 10px;
}</code></pre></div>



<h2 class="wp-block-heading">動作確認</h2>



<p>実装が完了したら、開発サーバーが起動している状態でブラウザを確認してください。以下の機能が動作することを確認できます。</p>


<div class="wp-block-image is-style-browser_mac size_xs">
<figure class="aligncenter size-full"><img decoding="async" width="1198" height="807" src="https://kekenta-it-blog.com/wp-content/uploads/2025/07/react_todo_series_05_01.jpg" alt="TODOアプリ（第５回：完成イメージ）その①" class="wp-image-15500" srcset="https://kekenta-it-blog.com/wp-content/uploads/2025/07/react_todo_series_05_01.jpg 1198w, https://kekenta-it-blog.com/wp-content/uploads/2025/07/react_todo_series_05_01-300x202.jpg 300w, https://kekenta-it-blog.com/wp-content/uploads/2025/07/react_todo_series_05_01-1024x690.jpg 1024w, https://kekenta-it-blog.com/wp-content/uploads/2025/07/react_todo_series_05_01-768x517.jpg 768w" sizes="(max-width: 1198px) 100vw, 1198px" /><figcaption class="wp-element-caption">TODOアプリ（第５回：完成イメージ）その①</figcaption></figure>
</div>

<div class="wp-block-image is-style-browser_mac size_xs">
<figure class="aligncenter size-full"><img decoding="async" width="1019" height="351" src="https://kekenta-it-blog.com/wp-content/uploads/2025/07/react_todo_series_05_02.jpg" alt="TODOアプリ（第５回：完成イメージ）その②" class="wp-image-15501" srcset="https://kekenta-it-blog.com/wp-content/uploads/2025/07/react_todo_series_05_02.jpg 1019w, https://kekenta-it-blog.com/wp-content/uploads/2025/07/react_todo_series_05_02-300x103.jpg 300w, https://kekenta-it-blog.com/wp-content/uploads/2025/07/react_todo_series_05_02-768x265.jpg 768w" sizes="(max-width: 1019px) 100vw, 1019px" /><figcaption class="wp-element-caption">TODOアプリ（第５回：完成イメージ）その②</figcaption></figure>
</div>

<div class="wp-block-image is-style-browser_mac size_xs">
<figure class="aligncenter size-full"><img decoding="async" width="995" height="235" src="https://kekenta-it-blog.com/wp-content/uploads/2025/07/react_todo_series_05_03.jpg" alt="TODOアプリ（第５回：完成イメージ）その③" class="wp-image-15502" srcset="https://kekenta-it-blog.com/wp-content/uploads/2025/07/react_todo_series_05_03.jpg 995w, https://kekenta-it-blog.com/wp-content/uploads/2025/07/react_todo_series_05_03-300x71.jpg 300w, https://kekenta-it-blog.com/wp-content/uploads/2025/07/react_todo_series_05_03-768x181.jpg 768w" sizes="(max-width: 995px) 100vw, 995px" /><figcaption class="wp-element-caption">TODOアプリ（第５回：完成イメージ）その③</figcaption></figure>
</div>

<div class="wp-block-image is-style-browser_mac size_xs">
<figure class="aligncenter size-full"><img decoding="async" width="951" height="303" src="https://kekenta-it-blog.com/wp-content/uploads/2025/07/react_todo_series_05_04.jpg" alt="TODOアプリ（第５回：完成イメージ）その④" class="wp-image-15499" srcset="https://kekenta-it-blog.com/wp-content/uploads/2025/07/react_todo_series_05_04.jpg 951w, https://kekenta-it-blog.com/wp-content/uploads/2025/07/react_todo_series_05_04-300x96.jpg 300w, https://kekenta-it-blog.com/wp-content/uploads/2025/07/react_todo_series_05_04-768x245.jpg 768w" sizes="(max-width: 951px) 100vw, 951px" /><figcaption class="wp-element-caption">TODOアプリ（第５回：完成イメージ）その④</figcaption></figure>
</div>


<div class="wp-block-group is-style-big_icon_good"><div class="wp-block-group__inner-container is-layout-constrained wp-block-group-is-layout-constrained">
<ul class="wp-block-list is-style-check_list -list-under-dashed">
<li>フィルターボタンでTODOリストを絞り込み表示</li>



<li>完了/未完了のバッジ表示</li>



<li>TODOが存在しない場合のメッセージ表示</li>



<li>アクティブなフィルターボタンのハイライト表示</li>
</ul>
</div></div>


<script async src="https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js?client=ca-pub-4374558503914683"
     crossorigin="anonymous"></script>
<!-- ディスプレイ【横長】 -->
<ins class="adsbygoogle"
     style="display:block"
     data-ad-client="ca-pub-4374558503914683"
     data-ad-slot="9744298852"
     data-ad-format="auto"
     data-full-width-responsive="true"></ins>
<script>
     (adsbygoogle = window.adsbygoogle || []).push({});
</script>



<h2 class="wp-block-heading">FAQ</h2>



<dl class="swell-block-faq -icon-circle is-style-faq-border" data-q="fill-custom" data-a="fill-main">
<div class="swell-block-faq__item"><dt class="faq_q">map関数でエラーが発生する場合</dt><dd class="faq_a">
<p>以下の点を確認してください。</p>



<ol class="wp-block-list">
<li>配列が正しく定義されているか</li>



<li>map関数の構文が正しいか</li>



<li>配列の要素が存在するか（空配列の場合は条件分岐を追加）</li>
</ol>
</dd></div>



<div class="swell-block-faq__item"><dt class="faq_q">keyプロパティの警告が表示される場合</dt><dd class="faq_a">
<p>以下の点を確認してください。</p>



<ol class="wp-block-list">
<li>各要素に一意のkeyプロパティが設定されているか</li>



<li>keyの値が安定しているか（配列のインデックスは避ける）</li>



<li>keyの値が重複していないか</li>
</ol>
</dd></div>



<div class="swell-block-faq__item"><dt class="faq_q">条件付きレンダリングが動作しない場合</dt><dd class="faq_a">
<p>以下の点を確認してください。</p>



<ol class="wp-block-list">
<li>条件式が正しく記述されているか</li>



<li>条件の値が期待する型になっているか</li>



<li>条件に応じた要素が正しく返されているか</li>
</ol>
</dd></div>



<div class="swell-block-faq__item"><dt class="faq_q">フィルタリングが動作しない場合</dt><dd class="faq_a">
<p>以下の点を確認してください。</p>



<ol class="wp-block-list">
<li>フィルター条件が正しく設定されているか</li>



<li>filter関数の構文が正しいか</li>



<li>フィルター状態が正しく更新されているか</li>
</ol>
</dd></div>



<div class="swell-block-faq__item"><dt class="faq_q">空の状態表示が動作しない場合</dt><dd class="faq_a">
<p>以下の点を確認してください。</p>



<ol class="wp-block-list">
<li>配列の長さチェックが正しく記述されているか</li>



<li>空の状態用のコンポーネントが正しく定義されているか</li>



<li>条件分岐の順序が適切か</li>
</ol>
</dd></div>



<div class="swell-block-faq__item"><dt class="faq_q">バッジやスタイルが表示されない場合</dt><dd class="faq_a">
<p>以下の点を確認してください。</p>



<ol class="wp-block-list">
<li>CSSクラス名が正しく記述されているか</li>



<li>条件付きレンダリングの構文が正しいか</li>



<li>CSSファイルが正しくimportされているか</li>
</ol>
</dd></div>
</dl>



<h2 class="wp-block-heading">まとめ</h2>



<p>今回は、Reactでのリスト表示と条件付きレンダリングについて学習しました。</p>



<p><code>map</code>関数を使ったリスト表示により、データに応じて動的にUIを生成することができるようになりました。また、<code>key</code>プロパティの重要性を理解し、効率的なリスト更新の方法を学びました。</p>



<p>条件付きレンダリングにより、ユーザーの操作やデータの状態に応じて適切なUIを表示することができるようになりました。</p>


<div class="swell-block-balloon"><div class="c-balloon -bln-left" data-col="gray"><div class="c-balloon__icon -circle"><img decoding="async" src="data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==" data-src="https://kekenta-it-blog.com/wp-content/uploads/2023/11/kekenta-icon-150x150.jpg" alt="" class="lazyload c-balloon__iconImg" width="80px" height="80px"><noscript><img decoding="async" src="https://kekenta-it-blog.com/wp-content/uploads/2023/11/kekenta-icon-150x150.jpg" alt="" class="c-balloon__iconImg" width="80px" height="80px"></noscript><span class="c-balloon__iconName">ケケンタ</span></div><div class="c-balloon__body -speaking -border-on"><div class="c-balloon__text">
<p>次回は、TODOの編集と削除機能について学習していきます。CRUD操作の実装を通じて、より実践的なアプリケーション開発を体験していきましょう！</p>
<span class="c-balloon__shapes"><span class="c-balloon__before"></span><span class="c-balloon__after"></span></span></div></div></div></div>


<p>この記事が少しでもお役に立ったなら何よりです。次回もお楽しみに！</p>


<div class="swell-block-postLink">			<div class="p-blogCard -internal" data-type="type2" data-onclick="clickLink">
				<div class="p-blogCard__inner">
					<span class="p-blogCard__caption">次の記事</span>
					<div class="p-blogCard__thumb c-postThumb"><figure class="c-postThumb__figure"><img decoding="async" src="https://kekenta-it-blog.com/wp-content/uploads/2025/07/eye-catch__react-todo-app-edit-delete-crud__15510-300x169.jpg" alt="" class="c-postThumb__img u-obf-cover" width="320" height="180"></figure></div>					<div class="p-blogCard__body">
						<a class="p-blogCard__title" href="https://kekenta-it-blog.com/react-todo-app-edit-delete-crud/">【React×TODOアプリ】編集・削除機能の実装【基本編：第6回】</a>
											</div>
				</div>
			</div>
		</div>

<div class="p-blogParts post_content" data-partsID="15579">
<hr class="wp-block-separator has-alpha-channel-opacity"/>



<p class="is-style-balloon_box"><span style="--the-icon-svg: url(data:image/svg+xml;base64,PHN2ZyBoZWlnaHQ9IjFlbSIgd2lkdGg9IjFlbSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiBhcmlhLWhpZGRlbj0idHJ1ZSIgdmlld0JveD0iMCAwIDQ4IDQ4Ij48cGF0aCBkPSJNMTEuNyAxLjQgNi44IDVjLS41LjQtLjggMS0uOCAxLjZ2MjguN2MwIC44LjUgMS41IDEuMiAxLjhsMjQgMTAuM2MxLjMuNiAyLjgtLjQgMi44LTEuOFYxOWMwLS44LS41LTEuNS0xLjItMS44TDEwLjIgNy41bDIuOS0yLjJjLjktLjYgMi0uOCAzLS40bDIwLjYgOC44Yy43LjMgMS4yIDEgMS4yIDEuOFY0Mi45YzAgLjkgMSAxLjMgMS43LjhsMS43LTEuNWMuNC0uNC43LS45LjctMS41VjEzYzAtLjgtLjUtMS41LTEuMi0xLjhMMTYuNy44Yy0xLjctLjctMy42LS41LTUgLjZ6Ij48L3BhdGg+PC9zdmc+)" data-icon="LsBook" data-id="0" aria-hidden="true" class="swl-inline-icon">  </span> <strong>僕が実際にReact学習に使用した書籍です</strong></p>


<div id="rinkerid15577" class="yyi-rinker-contents  yyi-rinker-postid-15577 yyi-rinker-img-m yyi-rinker-catid-256 ">
	<div class="yyi-rinker-box">
		<div class="yyi-rinker-image">
							<a href="https://www.amazon.co.jp/dp/B09BV2HGN3?tag=kekenta03am0b-22&#038;linkCode=ogi&#038;th=1&#038;psc=1" rel="nofollow" class="yyi-rinker-tracking"  data-click-tracking="amazon_img 15577 モダンJavaScriptの基本から始める　React実践の教科書　（最新ReactHooks対応）" data-vars-click-id="amazon_img 15577 モダンJavaScriptの基本から始める　React実践の教科書　（最新ReactHooks対応）"><img decoding="async" src="https://m.media-amazon.com/images/I/51Y0-P+m94L._SL160_.jpg"  width="112" height="160" class="yyi-rinker-main-img" style="border: none;"></a>					</div>
		<div class="yyi-rinker-info">
			<div class="yyi-rinker-title">
									<a href="https://www.amazon.co.jp/dp/B09BV2HGN3?tag=kekenta03am0b-22&#038;linkCode=ogi&#038;th=1&#038;psc=1" rel="nofollow" class="yyi-rinker-tracking" data-click-tracking="amazon_title 15577 モダンJavaScriptの基本から始める　React実践の教科書　（最新ReactHooks対応）" data-vars-amp-click-id="amazon_title 15577 モダンJavaScriptの基本から始める　React実践の教科書　（最新ReactHooks対応）" >モダンJavaScriptの基本から始める　React実践の教科書　（最新ReactHooks対応）</a>							</div>
			<div class="yyi-rinker-detail">
							<div class="credit-box">created by&nbsp;<a href="https://oyakosodate.com/rinker/" rel="nofollow noopener" target="_blank" >Rinker</a></div>
										<div class="price-box">
							</div>
						</div>
						<ul class="yyi-rinker-links">
																	<li class="amazonkindlelink">
						<a href="https://www.amazon.co.jp/dp/B09BV2HGN3?tag=kekenta03am0b-22&amp;linkCode=ogi&amp;th=1&amp;psc=1" rel="nofollow" class="yyi-rinker-link yyi-rinker-tracking"  data-click-tracking="amazon_kindle 15577 モダンJavaScriptの基本から始める　React実践の教科書　（最新ReactHooks対応）"  data-vars-amp-click-id="amazon_kindle 15577 モダンJavaScriptの基本から始める　React実践の教科書　（最新ReactHooks対応）">Kindle</a>					</li>
								                    <li class="amazonlink">
						<a href="https://www.amazon.co.jp/dp/B09BV2HGN3?tag=kekenta03am0b-22&amp;linkCode=ogi&amp;th=1&amp;psc=1" rel="nofollow" class="yyi-rinker-link yyi-rinker-tracking"  data-click-tracking="amazon 15577 モダンJavaScriptの基本から始める　React実践の教科書　（最新ReactHooks対応）"  data-vars-amp-click-id="amazon 15577 モダンJavaScriptの基本から始める　React実践の教科書　（最新ReactHooks対応）">Amazon</a>					</li>
													<li class="rakutenlink">
						<a href="https://hb.afl.rakuten.co.jp/hgc/3ace225e.aaf54072.3ace225f.2cf27f19/Rinker_o_20250722203529?pc=https%3A%2F%2Fsearch.rakuten.co.jp%2Fsearch%2Fmall%2F%25E3%2583%25A2%25E3%2583%2580%25E3%2583%25B3JavaScript%25E3%2581%25AE%25E5%259F%25BA%25E6%259C%25AC%25E3%2581%258B%25E3%2582%2589%25E5%25A7%258B%25E3%2582%2581%25E3%2582%258B%25E3%2580%2580React%25E5%25AE%259F%25E8%25B7%25B5%25E3%2581%25AE%25E6%2595%2599%25E7%25A7%2591%25E6%259B%25B8%25E3%2580%2580%25EF%25BC%2588%25E6%259C%2580%25E6%2596%25B0ReactHooks%25E5%25AF%25BE%25E5%25BF%259C%25EF%25BC%2589%2F%3Ff%3D1%26grp%3Dproduct&amp;m=https%3A%2F%2Fsearch.rakuten.co.jp%2Fsearch%2Fmall%2F%25E3%2583%25A2%25E3%2583%2580%25E3%2583%25B3JavaScript%25E3%2581%25AE%25E5%259F%25BA%25E6%259C%25AC%25E3%2581%258B%25E3%2582%2589%25E5%25A7%258B%25E3%2582%2581%25E3%2582%258B%25E3%2580%2580React%25E5%25AE%259F%25E8%25B7%25B5%25E3%2581%25AE%25E6%2595%2599%25E7%25A7%2591%25E6%259B%25B8%25E3%2580%2580%25EF%25BC%2588%25E6%259C%2580%25E6%2596%25B0ReactHooks%25E5%25AF%25BE%25E5%25BF%259C%25EF%25BC%2589%2F%3Ff%3D1%26grp%3Dproduct" rel="nofollow" class="yyi-rinker-link yyi-rinker-tracking"  data-click-tracking="rakuten 15577 モダンJavaScriptの基本から始める　React実践の教科書　（最新ReactHooks対応）"  data-vars-amp-click-id="rakuten 15577 モダンJavaScriptの基本から始める　React実践の教科書　（最新ReactHooks対応）">楽天市場</a>					</li>
								                											</ul>
					</div>
	</div>
</div>
</div>
]]></content:encoded>
					
					<wfw:commentRss>https://kekenta-it-blog.com/react-list-display-conditional-rendering/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>【React×TODOアプリ】イベントハンドリングとフォーム処理【基本編：第4回】</title>
		<link>https://kekenta-it-blog.com/react-event-handling-form-processing/</link>
					<comments>https://kekenta-it-blog.com/react-event-handling-form-processing/#respond</comments>
		
		<dc:creator><![CDATA[ケケンタ]]></dc:creator>
		<pubDate>Mon, 21 Jul 2025 11:56:56 +0000</pubDate>
				<category><![CDATA[React]]></category>
		<category><![CDATA[Javascript]]></category>
		<category><![CDATA[TODOアプリ]]></category>
		<category><![CDATA[開発シリーズ]]></category>
		<guid isPermaLink="false">https://kekenta-it-blog.com/?p=15483</guid>

					<description><![CDATA[<p><img src="https://kekenta-it-blog.com/wp-content/uploads/2025/07/eye-catch__react-event-handling-form-processing__15483-1024x576.jpg" class="webfeedsFeaturedVisual" /></p>Reactで作るTODOアプリ開発シリーズ第４回 この記事では Reactでのイベントハンドリングとフォーム処理の実装方法 を学習していきます。 前回はuseStateを使った状態管理について学習しました。今回は、ユーザ [&#8230;]]]></description>
										<content:encoded><![CDATA[<p><img src="https://kekenta-it-blog.com/wp-content/uploads/2025/07/eye-catch__react-event-handling-form-processing__15483-1024x576.jpg" class="webfeedsFeaturedVisual" /></p>
<p><strong>Reactで作るTODOアプリ開発シリーズ第４回</strong></p>



<p>この記事では</p>



<p class="has-text-align-center is-style-big_kakko_box"><strong>Reactでのイベントハンドリングとフォーム処理の実装方法</strong></p>



<p>を学習していきます。</p>


<div class="swell-block-postLink">			<div class="p-blogCard -internal" data-type="type2" data-onclick="clickLink">
				<div class="p-blogCard__inner">
					<span class="p-blogCard__caption">前回の記事</span>
					<div class="p-blogCard__thumb c-postThumb"><figure class="c-postThumb__figure"><img decoding="async" src="https://kekenta-it-blog.com/wp-content/uploads/2025/07/eye-catch__react-state-management-usestate__15448-300x169.jpg" alt="" class="c-postThumb__img u-obf-cover" width="320" height="180"></figure></div>					<div class="p-blogCard__body">
						<a class="p-blogCard__title" href="https://kekenta-it-blog.com/react-state-management-usestate/">【React×TODOアプリ】状態管理の基礎 &#8211; useState【基本編：第3回】</a>
											</div>
				</div>
			</div>
		</div>


<p><a href="https://kekenta-it-blog.com/react-state-management-usestate/">前回</a>は<strong>useStateを使った状態管理</strong>について学習しました。今回は、ユーザーの操作を受け取り、アプリケーションと対話できるようにするためのイベントハンドリングとフォーム処理について学んでいきましょう。</p>



<p>ユーザーがボタンをクリックしたり、フォームに入力したりしたときの処理を適切に実装することで、より使いやすいアプリケーションを作ることができます。</p>



<div class="swell-block-capbox cap_box"><div class="cap_box_ttl"><span><span style="--the-icon-svg: url(data:image/svg+xml;base64,PHN2ZyBoZWlnaHQ9IjFlbSIgd2lkdGg9IjFlbSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiBhcmlhLWhpZGRlbj0idHJ1ZSIgdmlld0JveD0iMCAwIDQ4IDQ4Ij48cGF0aCBkPSJNMzIgNDYuNUgxNmMtMS4xIDAtMi0uOS0yLTJzLjktMiAyLTJoMTZjMS4xIDAgMiAuOSAyIDJzLS45IDItMiAyek00MS43IDE1LjlDNDEuMyAxMyA0MCAxMC4zIDM4LjIgOCAzNC41IDMuMiAyOSAuOCAyMy4xIDEgMTQgMS40IDYuNSA4LjkgNiAxOGMtLjMgNiAyLjQgMTEuNyA3LjIgMTUuNC41LjQuOC45LjggMS41djEuNmMwIDIuMiAxLjggNCA0IDRoMTJjMi4yIDAgNC0xLjggNC00VjM1YzAtLjYuMy0xLjIuOS0xLjcgNS4zLTQgOC0xMC42IDYuOC0xNy40em0tNy4xIDEuN2gtLjNjLS43IDAtMS4zLS41LTEuNS0xLjItLjctMy4yLTMuMi01LjctNi40LTYuMy0uOC0uMS0xLjQtLjktMS4yLTEuN3MuOS0xLjQgMS43LTEuMmM0LjQuOCA4IDQuMiA4LjkgOC42LjEuOC0uNCAxLjYtMS4yIDEuOHoiPjwvcGF0aD48L3N2Zz4=)" data-icon="LsLightbulb" data-id="0" aria-hidden="true" class="swl-inline-icon"> </span> <strong>この記事でわかること</strong></span></div><div class="cap_box_content">
<ul class="wp-block-list is-style-check_list -list-under-dashed">
<li>イベントハンドラーの書き方と基本概念</li>



<li>フォームの制御（制御されたコンポーネント）</li>



<li>入力値の検証とバリデーション</li>



<li>TODO作成フォームの実装</li>



<li>エラーハンドリングの基礎</li>
</ul>
</div></div>


<div class="swell-block-balloon"><div class="c-balloon -bln-left" data-col="gray"><div class="c-balloon__icon -circle"><img decoding="async" src="data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==" data-src="https://kekenta-it-blog.com/wp-content/uploads/2023/07/キリッ-150x150.jpg" alt="" class="lazyload c-balloon__iconImg" width="80px" height="80px"><noscript><img decoding="async" src="https://kekenta-it-blog.com/wp-content/uploads/2023/07/キリッ-150x150.jpg" alt="" class="c-balloon__iconImg" width="80px" height="80px"></noscript><span class="c-balloon__iconName">ケケンタ</span></div><div class="c-balloon__body -speaking -border-on"><div class="c-balloon__text">
<p>イベントハンドリングを理解することで、ユーザーの操作に応じて動的に変化するインタラクティブなアプリケーションを作ることができるようになります！</p>
<span class="c-balloon__shapes"><span class="c-balloon__before"></span><span class="c-balloon__after"></span></span></div></div></div></div>

<div class="wp-block-image is-style-browser_mac size_xs">
<figure class="aligncenter size-full"><img decoding="async" width="1113" height="689" src="https://kekenta-it-blog.com/wp-content/uploads/2025/07/react_todo_series_04_01.jpg" alt="TODOアプリ（第４回：完成イメージ）その①" class="wp-image-15486" srcset="https://kekenta-it-blog.com/wp-content/uploads/2025/07/react_todo_series_04_01.jpg 1113w, https://kekenta-it-blog.com/wp-content/uploads/2025/07/react_todo_series_04_01-300x186.jpg 300w, https://kekenta-it-blog.com/wp-content/uploads/2025/07/react_todo_series_04_01-1024x634.jpg 1024w, https://kekenta-it-blog.com/wp-content/uploads/2025/07/react_todo_series_04_01-768x475.jpg 768w" sizes="(max-width: 1113px) 100vw, 1113px" /><figcaption class="wp-element-caption">TODOアプリ（第４回：完成イメージ）その①</figcaption></figure>
</div>

<div class="wp-block-image is-style-browser_mac size_xs">
<figure class="aligncenter size-full"><img decoding="async" width="959" height="230" src="https://kekenta-it-blog.com/wp-content/uploads/2025/07/react_todo_series_04_02.jpg" alt="TODOアプリ（第４回：完成イメージ）その②" class="wp-image-15487" srcset="https://kekenta-it-blog.com/wp-content/uploads/2025/07/react_todo_series_04_02.jpg 959w, https://kekenta-it-blog.com/wp-content/uploads/2025/07/react_todo_series_04_02-300x72.jpg 300w, https://kekenta-it-blog.com/wp-content/uploads/2025/07/react_todo_series_04_02-768x184.jpg 768w" sizes="(max-width: 959px) 100vw, 959px" /><figcaption class="wp-element-caption">TODOアプリ（第４回：完成イメージ）その②</figcaption></figure>
</div>

<div class="wp-block-image is-style-browser_mac size_xs">
<figure class="aligncenter size-full"><img decoding="async" width="938" height="218" src="https://kekenta-it-blog.com/wp-content/uploads/2025/07/react_todo_series_04_03.jpg" alt="TODOアプリ（第４回：完成イメージ）その③" class="wp-image-15488" srcset="https://kekenta-it-blog.com/wp-content/uploads/2025/07/react_todo_series_04_03.jpg 938w, https://kekenta-it-blog.com/wp-content/uploads/2025/07/react_todo_series_04_03-300x70.jpg 300w, https://kekenta-it-blog.com/wp-content/uploads/2025/07/react_todo_series_04_03-768x178.jpg 768w" sizes="(max-width: 938px) 100vw, 938px" /><figcaption class="wp-element-caption">TODOアプリ（第４回：完成イメージ）その③</figcaption></figure>
</div>


<p class="is-style-balloon_box"><span style="--the-icon-svg: url(data:image/svg+xml;base64,PHN2ZyBoZWlnaHQ9IjFlbSIgd2lkdGg9IjFlbSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiBhcmlhLWhpZGRlbj0idHJ1ZSIgdmlld0JveD0iMCAwIDQ4IDQ4Ij48cGF0aCBkPSJNMTAgM2gyOGMxLjEgMCAyIC45IDIgMnYzOS42YzAgLjktMS4xIDEuMy0xLjcuN0wyNCAzMSA5LjcgNDUuM2MtLjYuNi0xLjcuMi0xLjctLjdWNWMwLTEuMS45LTIgMi0yeiI+PC9wYXRoPjwvc3ZnPg==)" data-icon="LsBookmark" data-id="0" aria-hidden="true" class="swl-inline-icon"> </span> <strong>TODOアプリ開発シリーズのまとめ記事はこちら</strong></p>


<div class="swell-block-postLink">			<div class="p-blogCard -internal" data-type="type2" data-onclick="clickLink">
				<div class="p-blogCard__inner">
					<span class="p-blogCard__caption">シリーズ完全ガイド</span>
					<div class="p-blogCard__thumb c-postThumb"><figure class="c-postThumb__figure"><img decoding="async" src="https://kekenta-it-blog.com/wp-content/uploads/2025/07/eye-catch__react-todo-app-series-complete-guide-summary__15557-300x169.jpg" alt="" class="c-postThumb__img u-obf-cover" width="320" height="180"></figure></div>					<div class="p-blogCard__body">
						<a class="p-blogCard__title" href="https://kekenta-it-blog.com/react-todo-app-series-complete-guide-summary/">【React】初心者向けTODOアプリ開発シリーズ &#8211; 完全ガイドまとめ</a>
											</div>
				</div>
			</div>
		</div>


<h2 class="wp-block-heading">前回までのコード</h2>



<p>第3回で作成したコードを確認しましょう。以下のファイル構成になっています。</p>



<h3 class="wp-block-heading">ファイル構造</h3>



<div class="hcb_wrap"><pre class="prism line-numbers lang-plain"><code>todo-app/
├── src/
│   ├── App.js
│   ├── App.css
│   ├── TodoItem.js
│   ├── TodoList.js
│   └── TodoHeader.js</code></pre></div>



<h3 class="wp-block-heading">App.js</h3>



<div class="hcb_wrap"><pre class="prism line-numbers lang-js" data-lang="JavaScript"><code>import React, { useState } from &#39;react&#39;;
import &#39;./App.css&#39;;
import TodoHeader from &#39;./TodoHeader&#39;;
import TodoList from &#39;./TodoList&#39;;

function App() {
  const [todos, setTodos] = useState([
    { id: 1, text: &quot;Reactを学ぶ&quot;, completed: false, priority: &quot;high&quot; },
    { id: 2, text: &quot;TODOアプリを作る&quot;, completed: true, priority: &quot;medium&quot; },
    { id: 3, text: &quot;データベース連携&quot;, completed: false, priority: &quot;low&quot; },
    { id: 4, text: &quot;デプロイする&quot;, completed: false, priority: &quot;medium&quot; }
  ]);

  const completedCount = todos.filter(todo =&gt; todo.completed).length;

  // TODOの完了状態を切り替える関数
  const toggleTodo = (id) =&gt; {
    setTodos(prevTodos =&gt; 
      prevTodos.map(todo =&gt; 
        todo.id === id 
          ? { ...todo, completed: !todo.completed }
          : todo
      )
    );
  };

  return (
    &lt;div className=&quot;App&quot;&gt;
      &lt;TodoHeader 
        title=&quot;React TODOアプリ&quot;
        totalCount={todos.length}
        completedCount={completedCount}
      /&gt;
      &lt;TodoList todos={todos} onToggle={toggleTodo} /&gt;
    &lt;/div&gt;
  );
}

export default App;</code></pre></div>



<h3 class="wp-block-heading">TodoList.js</h3>



<div class="hcb_wrap"><pre class="prism line-numbers lang-js" data-lang="JavaScript"><code>import React from &#39;react&#39;;
import TodoItem from &#39;./TodoItem&#39;;

function TodoList({ todos, onToggle }) {
  return (
    &lt;div className=&quot;todo-list&quot;&gt;
      {todos.map((todo) =&gt; (
        &lt;TodoItem 
          key={todo.id}
          id={todo.id}
          text={todo.text}
          completed={todo.completed}
          priority={todo.priority}
          onToggle={onToggle}
        /&gt;
      ))}
    &lt;/div&gt;
  );
}

export default TodoList;</code></pre></div>



<h3 class="wp-block-heading">TodoItem.js</h3>



<div class="hcb_wrap"><pre class="prism line-numbers lang-js" data-lang="JavaScript"><code>import React from &#39;react&#39;;

function TodoItem({ id, text, completed, priority = &quot;medium&quot;, onToggle }) {
  return (
    &lt;div className={`todo-item priority-${priority}`}&gt;
      &lt;input 
        type=&quot;checkbox&quot; 
        checked={completed} 
        onChange={() =&gt; onToggle(id)}
      /&gt;
      &lt;span style={{ 
        textDecoration: completed ? &#39;line-through&#39; : &#39;none&#39; 
      }}&gt;
        {text}
      &lt;/span&gt;
    &lt;/div&gt;
  );
}

export default TodoItem;</code></pre></div>


<script async src="https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js?client=ca-pub-4374558503914683"
     crossorigin="anonymous"></script>
<!-- ディスプレイ【横長】 -->
<ins class="adsbygoogle"
     style="display:block"
     data-ad-client="ca-pub-4374558503914683"
     data-ad-slot="9744298852"
     data-ad-format="auto"
     data-full-width-responsive="true"></ins>
<script>
     (adsbygoogle = window.adsbygoogle || []).push({});
</script>



<h2 class="wp-block-heading">イベントハンドリングの基本</h2>



<p class="is-style-bg_stripe">実際に手を動かす前に、まずは必要な知識について解説をしていきます。</p>



<p>Reactでのイベントハンドリングは、HTMLのイベント処理と似ていますが、いくつかの重要な違いがあります。</p>



<h3 class="wp-block-heading">基本的なイベントハンドラー</h3>



<div class="hcb_wrap"><pre class="prism line-numbers lang-js" data-lang="JavaScript"><code>import React, { useState } from &#39;react&#39;;

function EventExample() {
  const [count, setCount] = useState(0);

  // クリックイベントのハンドラー
  const handleClick = () =&gt; {
    setCount(count + 1);
  };

  // マウスオーバーイベントのハンドラー
  const handleMouseOver = () =&gt; {
    console.log(&#39;マウスが上に来ました&#39;);
  };

  return (
    &lt;div&gt;
      &lt;p&gt;カウント: {count}&lt;/p&gt;
      &lt;button 
        onClick={handleClick}
        onMouseOver={handleMouseOver}
      &gt;
        クリックしてください
      &lt;/button&gt;
    &lt;/div&gt;
  );
}</code></pre></div>



<h3 class="wp-block-heading">イベントオブジェクトの使用</h3>



<p>イベントハンドラーは、イベントオブジェクトを引数として受け取ることができます。</p>



<div class="hcb_wrap"><pre class="prism line-numbers lang-js" data-lang="JavaScript"><code>function EventObjectExample() {
  const handleClick = (event) =&gt; {
    console.log(&#39;クリックされた要素:&#39;, event.target);
    console.log(&#39;クリックされた位置:&#39;, event.clientX, event.clientY);
  };

  const handleKeyPress = (event) =&gt; {
    if (event.key === &#39;Enter&#39;) {
      console.log(&#39;Enterキーが押されました&#39;);
    }
  };

  return (
    &lt;div&gt;
      &lt;button onClick={handleClick}&gt;
        クリックしてイベント情報を確認
      &lt;/button&gt;
      &lt;input 
        type=&quot;text&quot; 
        onKeyPress={handleKeyPress}
        placeholder=&quot;Enterキーを押してください&quot;
      /&gt;
    &lt;/div&gt;
  );
}</code></pre></div>



<h3 class="wp-block-heading">イベントの伝播と停止</h3>



<p>Reactでは、イベントの伝播（バブリング）を制御することができます。</p>



<div class="hcb_wrap"><pre class="prism line-numbers lang-js" data-lang="JavaScript"><code>function EventPropagationExample() {
  const handleParentClick = () =&gt; {
    console.log(&#39;親要素がクリックされました&#39;);
  };

  const handleChildClick = (event) =&gt; {
    console.log(&#39;子要素がクリックされました&#39;);
    event.stopPropagation(); // イベントの伝播を停止
  };

  return (
    &lt;div 
      onClick={handleParentClick}
      style={{ padding: &#39;20px&#39;, border: &#39;1px solid black&#39; }}
    &gt;
      親要素
      &lt;button onClick={handleChildClick}&gt;
        子要素（クリックしても親に伝播しません）
      &lt;/button&gt;
    &lt;/div&gt;
  );
}</code></pre></div>



<h2 class="wp-block-heading">フォームの制御（制御されたコンポーネント）</h2>



<p>Reactでは、フォームの値を状態で管理することで、入力値を完全に制御できます。これを「制御されたコンポーネント」と呼びます。</p>



<h3 class="wp-block-heading">基本的な制御されたコンポーネント</h3>



<div class="hcb_wrap"><pre class="prism line-numbers lang-js" data-lang="JavaScript"><code>import React, { useState } from &#39;react&#39;;

function ControlledForm() {
  const [inputValue, setInputValue] = useState(&#39;&#39;);

  const handleChange = (event) =&gt; {
    setInputValue(event.target.value);
  };

  const handleSubmit = (event) =&gt; {
    event.preventDefault(); // フォームのデフォルト動作を防ぐ
    console.log(&#39;送信された値:&#39;, inputValue);
    setInputValue(&#39;&#39;); // 送信後にフォームをクリア
  };

  return (
    &lt;form onSubmit={handleSubmit}&gt;
      &lt;input
        type=&quot;text&quot;
        value={inputValue}
        onChange={handleChange}
        placeholder=&quot;何か入力してください&quot;
      /&gt;
      &lt;button type=&quot;submit&quot;&gt;送信&lt;/button&gt;
    &lt;/form&gt;
  );
}</code></pre></div>



<h3 class="wp-block-heading">複数の入力フィールドの管理</h3>



<p>複数の入力フィールドがある場合は、オブジェクトで状態を管理します。</p>



<div class="hcb_wrap"><pre class="prism line-numbers lang-js" data-lang="JavaScript"><code>function MultiFieldForm() {
  const [formData, setFormData] = useState({
    name: &#39;&#39;,
    email: &#39;&#39;,
    message: &#39;&#39;
  });

  const handleChange = (event) =&gt; {
    const { name, value } = event.target;
    setFormData(prevData =&gt; ({
      ...prevData,
      [name]: value
    }));
  };

  const handleSubmit = (event) =&gt; {
    event.preventDefault();
    console.log(&#39;送信されたデータ:&#39;, formData);
  };

  return (
    &lt;form onSubmit={handleSubmit}&gt;
      &lt;div&gt;
        &lt;label htmlFor=&quot;name&quot;&gt;名前:&lt;/label&gt;
        &lt;input
          type=&quot;text&quot;
          id=&quot;name&quot;
          name=&quot;name&quot;
          value={formData.name}
          onChange={handleChange}
        /&gt;
      &lt;/div&gt;

      &lt;div&gt;
        &lt;label htmlFor=&quot;email&quot;&gt;メール:&lt;/label&gt;
        &lt;input
          type=&quot;email&quot;
          id=&quot;email&quot;
          name=&quot;email&quot;
          value={formData.email}
          onChange={handleChange}
        /&gt;
      &lt;/div&gt;

      &lt;div&gt;
        &lt;label htmlFor=&quot;message&quot;&gt;メッセージ:&lt;/label&gt;
        &lt;textarea
          id=&quot;message&quot;
          name=&quot;message&quot;
          value={formData.message}
          onChange={handleChange}
        /&gt;
      &lt;/div&gt;

      &lt;button type=&quot;submit&quot;&gt;送信&lt;/button&gt;
    &lt;/form&gt;
  );
}</code></pre></div>


<script async src="https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js?client=ca-pub-4374558503914683"
     crossorigin="anonymous"></script>
<!-- ディスプレイ【横長】 -->
<ins class="adsbygoogle"
     style="display:block"
     data-ad-client="ca-pub-4374558503914683"
     data-ad-slot="9744298852"
     data-ad-format="auto"
     data-full-width-responsive="true"></ins>
<script>
     (adsbygoogle = window.adsbygoogle || []).push({});
</script>



<h2 class="wp-block-heading">入力値の検証とバリデーション</h2>



<p>ユーザーの入力値を検証することで、より安全で使いやすいアプリケーションを作ることができます。</p>



<h3 class="wp-block-heading">基本的なバリデーション</h3>



<div class="hcb_wrap"><pre class="prism line-numbers lang-js" data-lang="JavaScript"><code>function ValidationExample() {
  const [inputValue, setInputValue] = useState(&#39;&#39;);
  const [error, setError] = useState(&#39;&#39;);

  const handleChange = (event) =&gt; {
    const value = event.target.value;
    setInputValue(value);

    // バリデーション
    if (value.length &lt; 3) {
      setError(&#39;3文字以上入力してください&#39;);
    } else if (value.length &gt; 20) {
      setError(&#39;20文字以下で入力してください&#39;);
    } else {
      setError(&#39;&#39;);
    }
  };

  const handleSubmit = (event) =&gt; {
    event.preventDefault();
    if (error) {
      alert(&#39;入力内容にエラーがあります&#39;);
      return;
    }
    console.log(&#39;送信:&#39;, inputValue);
  };

  return (
    &lt;form onSubmit={handleSubmit}&gt;
      &lt;input
        type=&quot;text&quot;
        value={inputValue}
        onChange={handleChange}
        placeholder=&quot;3-20文字で入力&quot;
      /&gt;
      {error && &lt;p style={{ color: &#39;red&#39; }}&gt;{error}&lt;/p&gt;}
      &lt;button type=&quot;submit&quot; disabled={!!error}&gt;
        送信
      &lt;/button&gt;
    &lt;/form&gt;
  );
}</code></pre></div>



<h3 class="wp-block-heading">リアルタイムバリデーション</h3>



<p>入力中にリアルタイムでバリデーションを行う例です。</p>



<div class="hcb_wrap"><pre class="prism line-numbers lang-js" data-lang="JavaScript"><code>function RealTimeValidation() {
  const [email, setEmail] = useState(&#39;&#39;);
  const [emailError, setEmailError] = useState(&#39;&#39;);

  const validateEmail = (email) =&gt; {
    const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
    return emailRegex.test(email);
  };

  const handleEmailChange = (event) =&gt; {
    const value = event.target.value;
    setEmail(value);

    if (value && !validateEmail(value)) {
      setEmailError(&#39;有効なメールアドレスを入力してください&#39;);
    } else {
      setEmailError(&#39;&#39;);
    }
  };

  return (
    &lt;div&gt;
      &lt;input
        type=&quot;email&quot;
        value={email}
        onChange={handleEmailChange}
        placeholder=&quot;メールアドレスを入力&quot;
      /&gt;
      {emailError && &lt;p style={{ color: &#39;red&#39; }}&gt;{emailError}&lt;/p&gt;}
    &lt;/div&gt;
  );
}</code></pre></div>



<h2 class="wp-block-heading">実装手順</h2>



<p class="is-style-bg_stripe">ここからは実際に手を動かして、TODOアプリに<strong>フォーム機能</strong>を追加していきましょう。</p>



<h3 class="wp-block-heading">1. TodoFormコンポーネントの作成</h3>



<p><code>src/TodoForm.js</code>ファイルを新規作成し、以下のコードを記述してください。</p>



<div class="hcb_wrap"><pre class="prism line-numbers lang-js" data-lang="JavaScript"><code>import React, { useState } from &#39;react&#39;;

function TodoForm({ onAddTodo }) {
  const [formData, setFormData] = useState({
    text: &#39;&#39;,
    priority: &#39;medium&#39;
  });
  const [error, setError] = useState(&#39;&#39;);

  const handleChange = (event) =&gt; {
    const { name, value } = event.target;
    setFormData(prevData =&gt; ({
      ...prevData,
      [name]: value
    }));

    // エラーをクリア
    if (error) {
      setError(&#39;&#39;);
    }
  };

  const handleSubmit = (event) =&gt; {
    event.preventDefault();

    // バリデーション
    if (!formData.text.trim()) {
      setError(&#39;TODOの内容を入力してください&#39;);
      return;
    }

    if (formData.text.length &gt; 100) {
      setError(&#39;TODOの内容は100文字以下で入力してください&#39;);
      return;
    }

    // 新しいTODOを作成
    const newTodo = {
      id: Date.now(),
      text: formData.text.trim(),
      completed: false,
      priority: formData.priority
    };

    // 親コンポーネントに新しいTODOを渡す
    onAddTodo(newTodo);

    // フォームをリセット
    setFormData({
      text: &#39;&#39;,
      priority: &#39;medium&#39;
    });
    setError(&#39;&#39;);
  };

  return (
    &lt;form onSubmit={handleSubmit} className=&quot;todo-form&quot;&gt;
      &lt;div className=&quot;form-group&quot;&gt;
        &lt;input
          type=&quot;text&quot;
          name=&quot;text&quot;
          value={formData.text}
          onChange={handleChange}
          placeholder=&quot;新しいTODOを入力してください&quot;
          className=&quot;todo-input&quot;
        /&gt;
        &lt;select
          name=&quot;priority&quot;
          value={formData.priority}
          onChange={handleChange}
          className=&quot;priority-select&quot;
        &gt;
          &lt;option value=&quot;low&quot;&gt;低優先度&lt;/option&gt;
          &lt;option value=&quot;medium&quot;&gt;中優先度&lt;/option&gt;
          &lt;option value=&quot;high&quot;&gt;高優先度&lt;/option&gt;
        &lt;/select&gt;
        &lt;button type=&quot;submit&quot; className=&quot;add-button&quot;&gt;
          追加
        &lt;/button&gt;
      &lt;/div&gt;
      {error && &lt;p className=&quot;error-message&quot;&gt;{error}&lt;/p&gt;}
    &lt;/form&gt;
  );
}

export default TodoForm;</code></pre></div>



<h3 class="wp-block-heading">2. App.jsの修正</h3>



<p>既存の<code>src/App.js</code>を以下のように修正してください。</p>



<div class="hcb_wrap"><pre class="prism line-numbers lang-js" data-lang="JavaScript"><code>import React, { useState } from &#39;react&#39;;
import &#39;./App.css&#39;;
import TodoHeader from &#39;./TodoHeader&#39;;
import TodoList from &#39;./TodoList&#39;;
import TodoForm from &#39;./TodoForm&#39;;

function App() {
  const [todos, setTodos] = useState([
    { id: 1, text: &quot;Reactを学ぶ&quot;, completed: false, priority: &quot;high&quot; },
    { id: 2, text: &quot;TODOアプリを作る&quot;, completed: true, priority: &quot;medium&quot; },
    { id: 3, text: &quot;データベース連携&quot;, completed: false, priority: &quot;low&quot; },
    { id: 4, text: &quot;デプロイする&quot;, completed: false, priority: &quot;medium&quot; }
  ]);

  const completedCount = todos.filter(todo =&gt; todo.completed).length;

  // TODOの完了状態を切り替える関数
  const toggleTodo = (id) =&gt; {
    setTodos(prevTodos =&gt; 
      prevTodos.map(todo =&gt; 
        todo.id === id 
          ? { ...todo, completed: !todo.completed }
          : todo
      )
    );
  };

  // 新しいTODOを追加する関数
  const addTodo = (newTodo) =&gt; {
    setTodos(prevTodos =&gt; [...prevTodos, newTodo]);
  };

  return (
    &lt;div className=&quot;App&quot;&gt;
      &lt;TodoHeader 
        title=&quot;React TODOアプリ&quot;
        totalCount={todos.length}
        completedCount={completedCount}
      /&gt;
      &lt;TodoForm onAddTodo={addTodo} /&gt;
      &lt;TodoList todos={todos} onToggle={toggleTodo} /&gt;
    &lt;/div&gt;
  );
}

export default App;</code></pre></div>



<h3 class="wp-block-heading">3. スタイルの追加</h3>



<p>既存の<code>src/App.css</code>に以下のスタイルを追加してください。</p>



<div class="hcb_wrap"><pre class="prism line-numbers lang-css" data-lang="CSS"><code>.todo-form {
  margin-bottom: 30px;
  padding: 20px;
  background-color: #f8f9fa;
  border-radius: 8px;
}

.form-group {
  display: flex;
  gap: 10px;
  align-items: center;
}

.todo-input {
  flex: 1;
  padding: 10px;
  border: 1px solid #ddd;
  border-radius: 4px;
  font-size: 16px;
}

.todo-input:focus {
  outline: none;
  border-color: #007bff;
  box-shadow: 0 0 0 2px rgba(0, 123, 255, 0.25);
}

.priority-select {
  padding: 10px;
  border: 1px solid #ddd;
  border-radius: 4px;
  font-size: 16px;
  background-color: white;
}

.add-button {
  padding: 10px 20px;
  background-color: #007bff;
  color: white;
  border: none;
  border-radius: 4px;
  font-size: 16px;
  cursor: pointer;
  transition: background-color 0.2s;
}

.add-button:hover {
  background-color: #0056b3;
}

.add-button:disabled {
  background-color: #6c757d;
  cursor: not-allowed;
}

.error-message {
  color: #dc3545;
  margin-top: 10px;
  font-size: 14px;
}</code></pre></div>



<h2 class="wp-block-heading">動作確認</h2>



<p>実装が完了したら、開発サーバーが起動している状態でブラウザを確認してください。以下の機能が動作することを確認できます。</p>


<div class="wp-block-image is-style-browser_mac size_xs">
<figure class="aligncenter size-full"><img decoding="async" width="1087" height="749" src="https://kekenta-it-blog.com/wp-content/uploads/2025/07/react_todo_series_04_04.jpg" alt="TODOアプリ（第４回：完成イメージ）その①" class="wp-image-15485" srcset="https://kekenta-it-blog.com/wp-content/uploads/2025/07/react_todo_series_04_04.jpg 1087w, https://kekenta-it-blog.com/wp-content/uploads/2025/07/react_todo_series_04_04-300x207.jpg 300w, https://kekenta-it-blog.com/wp-content/uploads/2025/07/react_todo_series_04_04-1024x706.jpg 1024w, https://kekenta-it-blog.com/wp-content/uploads/2025/07/react_todo_series_04_04-768x529.jpg 768w" sizes="(max-width: 1087px) 100vw, 1087px" /><figcaption class="wp-element-caption">TODOアプリ（第４回：完成イメージ）その①</figcaption></figure>
</div>

<div class="wp-block-image is-style-browser_mac size_xs">
<figure class="aligncenter size-full"><img decoding="async" width="959" height="230" src="https://kekenta-it-blog.com/wp-content/uploads/2025/07/react_todo_series_04_02.jpg" alt="TODOアプリ（第４回：完成イメージ）その②" class="wp-image-15487" srcset="https://kekenta-it-blog.com/wp-content/uploads/2025/07/react_todo_series_04_02.jpg 959w, https://kekenta-it-blog.com/wp-content/uploads/2025/07/react_todo_series_04_02-300x72.jpg 300w, https://kekenta-it-blog.com/wp-content/uploads/2025/07/react_todo_series_04_02-768x184.jpg 768w" sizes="(max-width: 959px) 100vw, 959px" /><figcaption class="wp-element-caption">TODOアプリ（第４回：完成イメージ）その②</figcaption></figure>
</div>

<div class="wp-block-image is-style-browser_mac size_xs">
<figure class="aligncenter size-full"><img decoding="async" width="938" height="218" src="https://kekenta-it-blog.com/wp-content/uploads/2025/07/react_todo_series_04_03.jpg" alt="TODOアプリ（第４回：完成イメージ）その③" class="wp-image-15488" srcset="https://kekenta-it-blog.com/wp-content/uploads/2025/07/react_todo_series_04_03.jpg 938w, https://kekenta-it-blog.com/wp-content/uploads/2025/07/react_todo_series_04_03-300x70.jpg 300w, https://kekenta-it-blog.com/wp-content/uploads/2025/07/react_todo_series_04_03-768x178.jpg 768w" sizes="(max-width: 938px) 100vw, 938px" /><figcaption class="wp-element-caption">TODOアプリ（第４回：完成イメージ）その③</figcaption></figure>
</div>


<div class="wp-block-group is-style-big_icon_good"><div class="wp-block-group__inner-container is-layout-constrained wp-block-group-is-layout-constrained">
<ul class="wp-block-list is-style-check_list -list-under-dashed">
<li>新しいTODOを入力して追加できる</li>



<li>優先度を選択できる</li>



<li>入力値のバリデーションが動作する</li>



<li>エラーメッセージが表示される</li>



<li>追加後にフォームがクリアされる</li>
</ul>
</div></div>


<script async src="https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js?client=ca-pub-4374558503914683"
     crossorigin="anonymous"></script>
<!-- ディスプレイ【横長】 -->
<ins class="adsbygoogle"
     style="display:block"
     data-ad-client="ca-pub-4374558503914683"
     data-ad-slot="9744298852"
     data-ad-format="auto"
     data-full-width-responsive="true"></ins>
<script>
     (adsbygoogle = window.adsbygoogle || []).push({});
</script>



<h2 class="wp-block-heading">FAQ</h2>



<dl class="swell-block-faq -icon-circle is-style-faq-border" data-q="fill-custom" data-a="fill-main">
<div class="swell-block-faq__item"><dt class="faq_q">イベントハンドラーでエラーが発生する場合</dt><dd class="faq_a">
<p>以下の点を確認してください。</p>



<ol class="wp-block-list">
<li>イベントハンドラー関数が正しく定義されているか</li>



<li>関数名が正しく記述されているか（onClick、onChangeなど）</li>



<li>関数が正しく呼び出されているか</li>
</ol>
</dd></div>



<div class="swell-block-faq__item"><dt class="faq_q">フォームの値が更新されない場合</dt><dd class="faq_a">
<p>以下の点を確認してください。</p>



<ol class="wp-block-list">
<li>value属性が正しく設定されているか</li>



<li>onChangeイベントハンドラーが正しく動作しているか</li>



<li>状態更新関数が正しく呼び出されているか</li>
</ol>
</dd></div>



<div class="swell-block-faq__item"><dt class="faq_q">フォーム送信でエラーが発生する場合</dt><dd class="faq_a">
<p>以下の点を確認してください。</p>



<ol class="wp-block-list">
<li>onSubmitイベントハンドラーが正しく設定されているか</li>



<li>e.preventDefault()が呼び出されているか</li>



<li>フォームのバリデーションが正しく動作しているか</li>
</ol>
</dd></div>



<div class="swell-block-faq__item"><dt class="faq_q">バリデーションが動作しない場合</dt><dd class="faq_a">
<p>以下の点を確認してください。</p>



<ol class="wp-block-list">
<li>バリデーション条件が正しく記述されているか</li>



<li>エラー状態が正しく更新されているか</li>



<li>エラーメッセージが正しく表示されているか</li>
</ol>
</dd></div>



<div class="swell-block-faq__item"><dt class="faq_q">フォームがクリアされない場合</dt><dd class="faq_a">
<p>以下の点を確認してください。</p>



<ol class="wp-block-list">
<li>フォーム送信後に状態が正しくリセットされているか</li>



<li>入力フィールドのvalue属性が正しく更新されているか</li>



<li>フォームの初期状態が正しく設定されているか</li>
</ol>
</dd></div>



<div class="swell-block-faq__item"><dt class="faq_q">キーボードイベントが動作しない場合</dt><dd class="faq_a">
<p>以下の点を確認してください。</p>



<ol class="wp-block-list">
<li>onKeyDownイベントハンドラーが正しく設定されているか</li>



<li>キーコードの判定が正しく記述されているか</li>



<li>イベントの伝播が正しく制御されているか</li>
</ol>
</dd></div>



<div class="swell-block-faq__item"><dt class="faq_q">フォームのスタイルが適用されない場合</dt><dd class="faq_a">
<p>以下の点を確認してください。</p>



<ol class="wp-block-list">
<li>CSSクラス名が正しく記述されているか</li>



<li>CSSファイルが正しくimportされているか</li>



<li>スタイルの優先度が適切か</li>
</ol>
</dd></div>
</dl>


<script async src="https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js?client=ca-pub-4374558503914683"
     crossorigin="anonymous"></script>
<!-- ディスプレイ【横長】 -->
<ins class="adsbygoogle"
     style="display:block"
     data-ad-client="ca-pub-4374558503914683"
     data-ad-slot="9744298852"
     data-ad-format="auto"
     data-full-width-responsive="true"></ins>
<script>
     (adsbygoogle = window.adsbygoogle || []).push({});
</script>



<h2 class="wp-block-heading">まとめ</h2>



<p>今回は、Reactでのイベントハンドリングとフォーム処理について学習しました。</p>



<p>制御されたコンポーネントを使うことで、フォームの値を完全に制御し、ユーザーの入力に応じて動的にUIを更新することができるようになりました。</p>



<p>バリデーション機能を実装することで、より安全で使いやすいアプリケーションを作ることができます。</p>


<div class="swell-block-balloon"><div class="c-balloon -bln-left" data-col="gray"><div class="c-balloon__icon -circle"><img decoding="async" src="data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==" data-src="https://kekenta-it-blog.com/wp-content/uploads/2023/11/kekenta-icon-150x150.jpg" alt="" class="lazyload c-balloon__iconImg" width="80px" height="80px"><noscript><img decoding="async" src="https://kekenta-it-blog.com/wp-content/uploads/2023/11/kekenta-icon-150x150.jpg" alt="" class="c-balloon__iconImg" width="80px" height="80px"></noscript><span class="c-balloon__iconName">ケケンタ</span></div><div class="c-balloon__body -speaking -border-on"><div class="c-balloon__text">
<p>次回は、リスト表示と条件付きレンダリングについて学習していきます。TODOリストの表示方法を改善し、フィルタリング機能を追加していきましょう！</p>
<span class="c-balloon__shapes"><span class="c-balloon__before"></span><span class="c-balloon__after"></span></span></div></div></div></div>


<p>この記事が少しでもお役に立ったなら何よりです。次回もお楽しみに！</p>


<div class="swell-block-postLink">			<div class="p-blogCard -internal" data-type="type2" data-onclick="clickLink">
				<div class="p-blogCard__inner">
					<span class="p-blogCard__caption">次の記事</span>
					<div class="p-blogCard__thumb c-postThumb"><figure class="c-postThumb__figure"><img decoding="async" src="https://kekenta-it-blog.com/wp-content/uploads/2025/07/eye-catch__react-list-display-conditional-rendering__15497-300x169.jpg" alt="" class="c-postThumb__img u-obf-cover" width="320" height="180"></figure></div>					<div class="p-blogCard__body">
						<a class="p-blogCard__title" href="https://kekenta-it-blog.com/react-list-display-conditional-rendering/">【React×TODOアプリ】リスト表示と条件付きレンダリング【基本編：第5回】</a>
											</div>
				</div>
			</div>
		</div>

<div class="p-blogParts post_content" data-partsID="15579">
<hr class="wp-block-separator has-alpha-channel-opacity"/>



<p class="is-style-balloon_box"><span style="--the-icon-svg: url(data:image/svg+xml;base64,PHN2ZyBoZWlnaHQ9IjFlbSIgd2lkdGg9IjFlbSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiBhcmlhLWhpZGRlbj0idHJ1ZSIgdmlld0JveD0iMCAwIDQ4IDQ4Ij48cGF0aCBkPSJNMTEuNyAxLjQgNi44IDVjLS41LjQtLjggMS0uOCAxLjZ2MjguN2MwIC44LjUgMS41IDEuMiAxLjhsMjQgMTAuM2MxLjMuNiAyLjgtLjQgMi44LTEuOFYxOWMwLS44LS41LTEuNS0xLjItMS44TDEwLjIgNy41bDIuOS0yLjJjLjktLjYgMi0uOCAzLS40bDIwLjYgOC44Yy43LjMgMS4yIDEgMS4yIDEuOFY0Mi45YzAgLjkgMSAxLjMgMS43LjhsMS43LTEuNWMuNC0uNC43LS45LjctMS41VjEzYzAtLjgtLjUtMS41LTEuMi0xLjhMMTYuNy44Yy0xLjctLjctMy42LS41LTUgLjZ6Ij48L3BhdGg+PC9zdmc+)" data-icon="LsBook" data-id="0" aria-hidden="true" class="swl-inline-icon">  </span> <strong>僕が実際にReact学習に使用した書籍です</strong></p>


<div id="rinkerid15577" class="yyi-rinker-contents  yyi-rinker-postid-15577 yyi-rinker-img-m yyi-rinker-catid-256 ">
	<div class="yyi-rinker-box">
		<div class="yyi-rinker-image">
							<a href="https://www.amazon.co.jp/dp/B09BV2HGN3?tag=kekenta03am0b-22&#038;linkCode=ogi&#038;th=1&#038;psc=1" rel="nofollow" class="yyi-rinker-tracking"  data-click-tracking="amazon_img 15577 モダンJavaScriptの基本から始める　React実践の教科書　（最新ReactHooks対応）" data-vars-click-id="amazon_img 15577 モダンJavaScriptの基本から始める　React実践の教科書　（最新ReactHooks対応）"><img decoding="async" src="https://m.media-amazon.com/images/I/51Y0-P+m94L._SL160_.jpg"  width="112" height="160" class="yyi-rinker-main-img" style="border: none;"></a>					</div>
		<div class="yyi-rinker-info">
			<div class="yyi-rinker-title">
									<a href="https://www.amazon.co.jp/dp/B09BV2HGN3?tag=kekenta03am0b-22&#038;linkCode=ogi&#038;th=1&#038;psc=1" rel="nofollow" class="yyi-rinker-tracking" data-click-tracking="amazon_title 15577 モダンJavaScriptの基本から始める　React実践の教科書　（最新ReactHooks対応）" data-vars-amp-click-id="amazon_title 15577 モダンJavaScriptの基本から始める　React実践の教科書　（最新ReactHooks対応）" >モダンJavaScriptの基本から始める　React実践の教科書　（最新ReactHooks対応）</a>							</div>
			<div class="yyi-rinker-detail">
							<div class="credit-box">created by&nbsp;<a href="https://oyakosodate.com/rinker/" rel="nofollow noopener" target="_blank" >Rinker</a></div>
										<div class="price-box">
							</div>
						</div>
						<ul class="yyi-rinker-links">
																	<li class="amazonkindlelink">
						<a href="https://www.amazon.co.jp/dp/B09BV2HGN3?tag=kekenta03am0b-22&amp;linkCode=ogi&amp;th=1&amp;psc=1" rel="nofollow" class="yyi-rinker-link yyi-rinker-tracking"  data-click-tracking="amazon_kindle 15577 モダンJavaScriptの基本から始める　React実践の教科書　（最新ReactHooks対応）"  data-vars-amp-click-id="amazon_kindle 15577 モダンJavaScriptの基本から始める　React実践の教科書　（最新ReactHooks対応）">Kindle</a>					</li>
								                    <li class="amazonlink">
						<a href="https://www.amazon.co.jp/dp/B09BV2HGN3?tag=kekenta03am0b-22&amp;linkCode=ogi&amp;th=1&amp;psc=1" rel="nofollow" class="yyi-rinker-link yyi-rinker-tracking"  data-click-tracking="amazon 15577 モダンJavaScriptの基本から始める　React実践の教科書　（最新ReactHooks対応）"  data-vars-amp-click-id="amazon 15577 モダンJavaScriptの基本から始める　React実践の教科書　（最新ReactHooks対応）">Amazon</a>					</li>
													<li class="rakutenlink">
						<a href="https://hb.afl.rakuten.co.jp/hgc/3ace225e.aaf54072.3ace225f.2cf27f19/Rinker_o_20250722203529?pc=https%3A%2F%2Fsearch.rakuten.co.jp%2Fsearch%2Fmall%2F%25E3%2583%25A2%25E3%2583%2580%25E3%2583%25B3JavaScript%25E3%2581%25AE%25E5%259F%25BA%25E6%259C%25AC%25E3%2581%258B%25E3%2582%2589%25E5%25A7%258B%25E3%2582%2581%25E3%2582%258B%25E3%2580%2580React%25E5%25AE%259F%25E8%25B7%25B5%25E3%2581%25AE%25E6%2595%2599%25E7%25A7%2591%25E6%259B%25B8%25E3%2580%2580%25EF%25BC%2588%25E6%259C%2580%25E6%2596%25B0ReactHooks%25E5%25AF%25BE%25E5%25BF%259C%25EF%25BC%2589%2F%3Ff%3D1%26grp%3Dproduct&amp;m=https%3A%2F%2Fsearch.rakuten.co.jp%2Fsearch%2Fmall%2F%25E3%2583%25A2%25E3%2583%2580%25E3%2583%25B3JavaScript%25E3%2581%25AE%25E5%259F%25BA%25E6%259C%25AC%25E3%2581%258B%25E3%2582%2589%25E5%25A7%258B%25E3%2582%2581%25E3%2582%258B%25E3%2580%2580React%25E5%25AE%259F%25E8%25B7%25B5%25E3%2581%25AE%25E6%2595%2599%25E7%25A7%2591%25E6%259B%25B8%25E3%2580%2580%25EF%25BC%2588%25E6%259C%2580%25E6%2596%25B0ReactHooks%25E5%25AF%25BE%25E5%25BF%259C%25EF%25BC%2589%2F%3Ff%3D1%26grp%3Dproduct" rel="nofollow" class="yyi-rinker-link yyi-rinker-tracking"  data-click-tracking="rakuten 15577 モダンJavaScriptの基本から始める　React実践の教科書　（最新ReactHooks対応）"  data-vars-amp-click-id="rakuten 15577 モダンJavaScriptの基本から始める　React実践の教科書　（最新ReactHooks対応）">楽天市場</a>					</li>
								                											</ul>
					</div>
	</div>
</div>
</div>
]]></content:encoded>
					
					<wfw:commentRss>https://kekenta-it-blog.com/react-event-handling-form-processing/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>【React×TODOアプリ】状態管理の基礎 &#8211; useState【基本編：第3回】</title>
		<link>https://kekenta-it-blog.com/react-state-management-usestate/</link>
					<comments>https://kekenta-it-blog.com/react-state-management-usestate/#respond</comments>
		
		<dc:creator><![CDATA[ケケンタ]]></dc:creator>
		<pubDate>Mon, 21 Jul 2025 06:46:21 +0000</pubDate>
				<category><![CDATA[React]]></category>
		<category><![CDATA[Javascript]]></category>
		<category><![CDATA[TODOアプリ]]></category>
		<category><![CDATA[開発シリーズ]]></category>
		<guid isPermaLink="false">https://kekenta-it-blog.com/?p=15448</guid>

					<description><![CDATA[<p><img src="https://kekenta-it-blog.com/wp-content/uploads/2025/07/eye-catch__react-state-management-usestate__15448-1024x576.jpg" class="webfeedsFeaturedVisual" /></p>Reactで作るTODOアプリ開発シリーズ第３回 この記事では Reactでの状態管理の基礎、useStateフックの使い方 を学習していきます。 前回は、コンポーネントとJSXについて詳しく学習しました。今回は、Rea [&#8230;]]]></description>
										<content:encoded><![CDATA[<p><img src="https://kekenta-it-blog.com/wp-content/uploads/2025/07/eye-catch__react-state-management-usestate__15448-1024x576.jpg" class="webfeedsFeaturedVisual" /></p>
<p><strong>Reactで作るTODOアプリ開発シリーズ第３回</strong></p>



<p>この記事では</p>



<p class="has-text-align-center is-style-big_kakko_box"><strong>Reactでの状態管理の基礎、useStateフックの使い方</strong></p>



<p>を学習していきます。</p>


<div class="swell-block-postLink">			<div class="p-blogCard -internal" data-type="type2" data-onclick="clickLink">
				<div class="p-blogCard__inner">
					<span class="p-blogCard__caption">前回の記事</span>
					<div class="p-blogCard__thumb c-postThumb"><figure class="c-postThumb__figure"><img decoding="async" src="https://kekenta-it-blog.com/wp-content/uploads/2025/07/eye-catch__react-components-jsx-understanding__15432-300x169.jpg" alt="" class="c-postThumb__img u-obf-cover" width="320" height="180"></figure></div>					<div class="p-blogCard__body">
						<a class="p-blogCard__title" href="https://kekenta-it-blog.com/react-components-jsx-understanding/">【React×TODOアプリ】コンポーネントとJSXの理解【基本編：第2回】</a>
											</div>
				</div>
			</div>
		</div>


<p><a href="https://kekenta-it-blog.com/react-components-jsx-understanding/">前回</a>は、<strong>コンポーネントとJSX</strong>について詳しく学習しました。今回は、Reactアプリケーションを動的にするために欠かせない状態管理について学んでいきましょう。</p>



<p>useStateは、Reactの最も基本的なフックの一つです。これを使うことで、コンポーネント内でデータを保持し、そのデータが変更されたときに自動的にUIを更新することができます。</p>



<div class="swell-block-capbox cap_box"><div class="cap_box_ttl"><span><span data-icon="LsLightbulb" data-id="0" style="--the-icon-svg: url(data:image/svg+xml;base64,PHN2ZyBoZWlnaHQ9IjFlbSIgd2lkdGg9IjFlbSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiBhcmlhLWhpZGRlbj0idHJ1ZSIgdmlld0JveD0iMCAwIDQ4IDQ4Ij48cGF0aCBkPSJNMzIgNDYuNUgxNmMtMS4xIDAtMi0uOS0yLTJzLjktMiAyLTJoMTZjMS4xIDAgMiAuOSAyIDJzLS45IDItMiAyek00MS43IDE1LjlDNDEuMyAxMyA0MCAxMC4zIDM4LjIgOCAzNC41IDMuMiAyOSAuOCAyMy4xIDEgMTQgMS40IDYuNSA4LjkgNiAxOGMtLjMgNiAyLjQgMTEuNyA3LjIgMTUuNC41LjQuOC45LjggMS41djEuNmMwIDIuMiAxLjggNCA0IDRoMTJjMi4yIDAgNC0xLjggNC00VjM1YzAtLjYuMy0xLjIuOS0xLjcgNS4zLTQgOC0xMC42IDYuOC0xNy40em0tNy4xIDEuN2gtLjNjLS43IDAtMS4zLS41LTEuNS0xLjItLjctMy4yLTMuMi01LjctNi40LTYuMy0uOC0uMS0xLjQtLjktMS4yLTEuN3MuOS0xLjQgMS43LTEuMmM0LjQuOCA4IDQuMiA4LjkgOC42LjEuOC0uNCAxLjYtMS4yIDEuOHoiPjwvcGF0aD48L3N2Zz4=)" aria-hidden="true" class="swl-inline-icon"> </span> <strong>この記事でわかること</strong></span></div><div class="cap_box_content">
<ul class="wp-block-list is-style-check_list -list-under-dashed">
<li>useStateフックの基本概念</li>



<li>状態の更新方法と注意点</li>



<li>配列とオブジェクトの状態管理</li>



<li>TODOリストの基本構造作成</li>



<li>TODOアイテムの追加機能実装</li>
</ul>
</div></div>


<div class="swell-block-balloon"><div class="c-balloon -bln-left" data-col="gray"><div class="c-balloon__icon -circle"><img decoding="async" src="data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==" data-src="https://kekenta-it-blog.com/wp-content/uploads/2023/07/キリッ-150x150.jpg" alt="" class="lazyload c-balloon__iconImg" width="80px" height="80px"><noscript><img decoding="async" src="https://kekenta-it-blog.com/wp-content/uploads/2023/07/キリッ-150x150.jpg" alt="" class="c-balloon__iconImg" width="80px" height="80px"></noscript><span class="c-balloon__iconName">ケケンタ</span></div><div class="c-balloon__body -speaking -border-on"><div class="c-balloon__text">
<p>状態管理を理解することで、ユーザーの操作に応じて動的に変化するアプリケーションを作ることができるようになります！</p>
<span class="c-balloon__shapes"><span class="c-balloon__before"></span><span class="c-balloon__after"></span></span></div></div></div></div>

<div class="wp-block-image is-style-browser_mac size_xs">
<figure class="aligncenter size-full"><img decoding="async" width="1021" height="526" src="https://kekenta-it-blog.com/wp-content/uploads/2025/07/react_todo_series_03_01.jpg" alt="TODOアプリ（第３回：完成イメージ）" class="wp-image-15450" srcset="https://kekenta-it-blog.com/wp-content/uploads/2025/07/react_todo_series_03_01.jpg 1021w, https://kekenta-it-blog.com/wp-content/uploads/2025/07/react_todo_series_03_01-300x155.jpg 300w, https://kekenta-it-blog.com/wp-content/uploads/2025/07/react_todo_series_03_01-768x396.jpg 768w" sizes="(max-width: 1021px) 100vw, 1021px" /><figcaption class="wp-element-caption">TODOアプリ（第３回：完成イメージ）</figcaption></figure>
</div>


<p class="is-style-balloon_box"><span style="--the-icon-svg: url(data:image/svg+xml;base64,PHN2ZyBoZWlnaHQ9IjFlbSIgd2lkdGg9IjFlbSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiBhcmlhLWhpZGRlbj0idHJ1ZSIgdmlld0JveD0iMCAwIDQ4IDQ4Ij48cGF0aCBkPSJNMTAgM2gyOGMxLjEgMCAyIC45IDIgMnYzOS42YzAgLjktMS4xIDEuMy0xLjcuN0wyNCAzMSA5LjcgNDUuM2MtLjYuNi0xLjcuMi0xLjctLjdWNWMwLTEuMS45LTIgMi0yeiI+PC9wYXRoPjwvc3ZnPg==)" data-icon="LsBookmark" data-id="0" aria-hidden="true" class="swl-inline-icon"> </span> <strong>TODOアプリ開発シリーズのまとめ記事はこちら</strong></p>


<div class="swell-block-postLink">			<div class="p-blogCard -internal" data-type="type2" data-onclick="clickLink">
				<div class="p-blogCard__inner">
					<span class="p-blogCard__caption">シリーズ完全ガイド</span>
					<div class="p-blogCard__thumb c-postThumb"><figure class="c-postThumb__figure"><img decoding="async" src="https://kekenta-it-blog.com/wp-content/uploads/2025/07/eye-catch__react-todo-app-series-complete-guide-summary__15557-300x169.jpg" alt="" class="c-postThumb__img u-obf-cover" width="320" height="180"></figure></div>					<div class="p-blogCard__body">
						<a class="p-blogCard__title" href="https://kekenta-it-blog.com/react-todo-app-series-complete-guide-summary/">【React】初心者向けTODOアプリ開発シリーズ &#8211; 完全ガイドまとめ</a>
											</div>
				</div>
			</div>
		</div>


<h2 class="wp-block-heading">前回までのコード</h2>



<p>第2回で作成したコードを確認しましょう。以下のファイル構成になっています：</p>



<h3 class="wp-block-heading">ファイル構造</h3>



<div class="hcb_wrap"><pre class="prism line-numbers lang-plain"><code>todo-app/
├── src/
│   ├── App.js
│   ├── App.css
│   ├── TodoItem.js
│   ├── TodoList.js
│   └── TodoHeader.js</code></pre></div>



<h3 class="wp-block-heading">App.js</h3>



<div class="hcb_wrap"><pre class="prism line-numbers lang-js" data-lang="JavaScript"><code>import React from &#39;react&#39;;
import &#39;./App.css&#39;;
import TodoHeader from &#39;./TodoHeader&#39;;
import TodoList from &#39;./TodoList&#39;;

function App() {
  const todos = [
    { text: &quot;Reactを学ぶ&quot;, completed: false, priority: &quot;high&quot; },
    { text: &quot;TODOアプリを作る&quot;, completed: true, priority: &quot;medium&quot; },
    { text: &quot;データベース連携&quot;, completed: false, priority: &quot;low&quot; },
    { text: &quot;デプロイする&quot;, completed: false, priority: &quot;medium&quot; }
  ];

  const completedCount = todos.filter(todo =&gt; todo.completed).length;

  return (
    &lt;div className=&quot;App&quot;&gt;
      &lt;TodoHeader 
        title=&quot;React TODOアプリ&quot;
        totalCount={todos.length}
        completedCount={completedCount}
      /&gt;
      &lt;TodoList todos={todos} /&gt;
    &lt;/div&gt;
  );
}

export default App;</code></pre></div>



<h3 class="wp-block-heading">TodoList.js</h3>



<div class="hcb_wrap"><pre class="prism line-numbers lang-js" data-lang="JavaScript"><code>import React from &#39;react&#39;;
import TodoItem from &#39;./TodoItem&#39;;

function TodoList({ todos }) {
  return (
    &lt;div className=&quot;todo-list&quot;&gt;
      {todos.map((todo, index) =&gt; (
        &lt;TodoItem 
          key={index}
          text={todo.text}
          completed={todo.completed}
          priority={todo.priority}
        /&gt;
      ))}
    &lt;/div&gt;
  );
}

export default TodoList;</code></pre></div>



<h3 class="wp-block-heading">TodoHeader.js</h3>



<div class="hcb_wrap"><pre class="prism line-numbers lang-js" data-lang="JavaScript"><code>import React from &#39;react&#39;;

function TodoHeader({ title, totalCount, completedCount }) {
  return (
    &lt;div className=&quot;todo-header&quot;&gt;
      &lt;h1&gt;{title}&lt;/h1&gt;
      &lt;div className=&quot;todo-stats&quot;&gt;
        &lt;span&gt;総数: {totalCount}&lt;/span&gt;
        &lt;span&gt;完了: {completedCount}&lt;/span&gt;
        &lt;span&gt;未完了: {totalCount - completedCount}&lt;/span&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  );
}

export default TodoHeader;</code></pre></div>



<h3 class="wp-block-heading">TodoItem.js</h3>



<div class="hcb_wrap"><pre class="prism line-numbers lang-js" data-lang="JavaScript"><code>import React from &#39;react&#39;;

function TodoItem({ text, completed, priority = &quot;medium&quot; }) {
  return (
    &lt;div className={`todo-item priority-${priority}`}&gt;
      &lt;input 
        type=&quot;checkbox&quot; 
        checked={completed} 
        readOnly 
      /&gt;
      &lt;span style={{ 
        textDecoration: completed ? &#39;line-through&#39; : &#39;none&#39; 
      }}&gt;
        {text}
      &lt;/span&gt;
    &lt;/div&gt;
  );
}

export default TodoItem;</code></pre></div>



<h3 class="wp-block-heading">App.css</h3>



<div class="hcb_wrap"><pre class="prism line-numbers lang-css" data-lang="CSS"><code>.todo-header {
  margin-bottom: 30px;
}

.todo-stats {
  display: flex;
  justify-content: center;
  gap: 20px;
  margin-top: 10px;
  font-size: 14px;
  color: #666;
}

.todo-stats span {
  padding: 5px 10px;
  background-color: #f5f5f5;
  border-radius: 15px;
}

.priority-high {
  border-left: 4px solid #ff4757;
}

.priority-medium {
  border-left: 4px solid #ffa502;
}

.priority-low {
  border-left: 4px solid #2ed573;
}</code></pre></div>


<script async src="https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js?client=ca-pub-4374558503914683"
     crossorigin="anonymous"></script>
<!-- ディスプレイ【横長】 -->
<ins class="adsbygoogle"
     style="display:block"
     data-ad-client="ca-pub-4374558503914683"
     data-ad-slot="9744298852"
     data-ad-format="auto"
     data-full-width-responsive="true"></ins>
<script>
     (adsbygoogle = window.adsbygoogle || []).push({});
</script>



<h2 class="wp-block-heading">useStateフックの基本概念</h2>



<p class="is-style-bg_stripe">実際に手を動かす前に、まずは必要な知識について解説をしていきます。</p>



<p><strong>useState</strong>は、<strong>Reactコンポーネントで状態（state）を管理するためのフック</strong>です。状態とは、コンポーネントが保持するデータで、このデータが変更されると自動的にコンポーネントが再レンダリングされます。</p>



<h3 class="wp-block-heading">useStateの基本構文</h3>



<div class="hcb_wrap"><pre class="prism line-numbers lang-js" data-lang="JavaScript"><code>import React, { useState } from &#39;react&#39;;

function Counter() {
  const [count, setCount] = useState(0);

  return (
    &lt;div&gt;
      &lt;p&gt;カウント: {count}&lt;/p&gt;
      &lt;button onClick={() =&gt; setCount(count + 1)}&gt;
        増やす
      &lt;/button&gt;
    &lt;/div&gt;
  );
}</code></pre></div>



<h3 class="wp-block-heading">useStateの仕組み</h3>



<div class="wp-block-group has-border -border01"><div class="wp-block-group__inner-container is-layout-constrained wp-block-group-is-layout-constrained">
<ol class="wp-block-list -list-under-dashed is-style-num_circle">
<li><strong>初期値の設定</strong>: <code>useState(0)</code>で初期値を0に設定</li>



<li><strong>状態とセッター関数</strong>: <code>[count, setCount]</code>で分割代入</li>
</ol>



<div class="wp-block-group is-style-big_icon_memo"><div class="wp-block-group__inner-container is-layout-constrained wp-block-group-is-layout-constrained">
<ul class="wp-block-list is-style-check_list">
<li><code>count</code>: 現在の状態値</li>



<li><code>setCount</code>: 状態を更新する関数</li>
</ul>
</div></div>
</div></div>



<div class="wp-block-group has-border -border01"><div class="wp-block-group__inner-container is-layout-constrained wp-block-group-is-layout-constrained">
<ol class="wp-block-list is-style-num_circle -list-under-dashed">
<li><strong>状態の更新</strong>: <code>setCount(count + 1)</code>で状態を更新</li>



<li><strong>自動再レンダリング</strong>: 状態が更新されると自動的にコンポーネントが再描画</li>
</ol>
</div></div>



<h2 class="wp-block-heading">状態の更新方法と注意点</h2>



<h3 class="wp-block-heading">基本的な状態更新</h3>



<div class="hcb_wrap"><pre class="prism line-numbers lang-js" data-lang="JavaScript"><code>function Example() {
  const [name, setName] = useState(&quot;React&quot;);

  const handleClick = () =&gt; {
    setName(&quot;JavaScript&quot;); // 直接値を設定
  };

  return (
    &lt;div&gt;
      &lt;p&gt;名前: {name}&lt;/p&gt;
      &lt;button onClick={handleClick}&gt;名前を変更&lt;/button&gt;
    &lt;/div&gt;
  );
}</code></pre></div>



<h3 class="wp-block-heading">関数を使った状態更新</h3>



<p class="is-style-icon_pen">前の状態をもとに新しい状態を計算する場合は、関数を使うことができます。</p>



<div class="hcb_wrap"><pre class="prism line-numbers lang-js" data-lang="JavaScript"><code>function Counter() {
  const [count, setCount] = useState(0);

  const increment = () =&gt; {
    setCount(prevCount =&gt; prevCount + 1); // 前の状態を基に更新
  };

  const decrement = () =&gt; {
    setCount(prevCount =&gt; prevCount - 1);
  };

  return (
    &lt;div&gt;
      &lt;p&gt;カウント: {count}&lt;/p&gt;
      &lt;button onClick={increment}&gt;+1&lt;/button&gt;
      &lt;button onClick={decrement}&gt;-1&lt;/button&gt;
    &lt;/div&gt;
  );
}</code></pre></div>



<h3 class="wp-block-heading">重要な注意点</h3>



<p class="is-style-icon_info">状態の更新は非同期で行われるため、以下のような書き方は避けるべきです。</p>



<div class="hcb_wrap"><pre class="prism line-numbers lang-js" data-lang="JavaScript"><code>// ❌ 避けるべき書き方
function BadExample() {
  const [count, setCount] = useState(0);

  const handleClick = () =&gt; {
    setCount(count + 1);
    setCount(count + 1); // 前の更新が反映される前に実行される
  };
}

// ✅ 正しい書き方
function GoodExample() {
  const [count, setCount] = useState(0);

  const handleClick = () =&gt; {
    setCount(prevCount =&gt; prevCount + 1);
    setCount(prevCount =&gt; prevCount + 1); // 前の状態を基に更新
  };
}</code></pre></div>


<script async src="https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js?client=ca-pub-4374558503914683"
     crossorigin="anonymous"></script>
<!-- ディスプレイ【横長】 -->
<ins class="adsbygoogle"
     style="display:block"
     data-ad-client="ca-pub-4374558503914683"
     data-ad-slot="9744298852"
     data-ad-format="auto"
     data-full-width-responsive="true"></ins>
<script>
     (adsbygoogle = window.adsbygoogle || []).push({});
</script>



<h2 class="wp-block-heading">配列とオブジェクトの状態管理</h2>



<h3 class="wp-block-heading">配列の状態管理</h3>



<p class="is-style-icon_pen">配列の状態を更新する際は、元の配列を変更せずに新しい配列を作成する必要があります。</p>



<div class="hcb_wrap"><pre class="prism line-numbers lang-js" data-lang="JavaScript"><code>function TodoList() {
  const [todos, setTodos] = useState([
    { id: 1, text: &quot;Reactを学ぶ&quot;, completed: false },
    { id: 2, text: &quot;TODOアプリを作る&quot;, completed: true }
  ]);

  // 新しいTODOを追加
  const addTodo = (text) =&gt; {
    const newTodo = {
      id: Date.now(), // 簡単なID生成
      text: text,
      completed: false
    };
    setTodos(prevTodos =&gt; [...prevTodos, newTodo]); // スプレッド構文で新しい配列を作成
  };

  // TODOを削除
  const deleteTodo = (id) =&gt; {
    setTodos(prevTodos =&gt; prevTodos.filter(todo =&gt; todo.id !== id));
  };

  // TODOの完了状態を切り替え
  const toggleTodo = (id) =&gt; {
    setTodos(prevTodos =&gt; 
      prevTodos.map(todo =&gt; 
        todo.id === id 
          ? { ...todo, completed: !todo.completed }
          : todo
      )
    );
  };

  return (
    &lt;div&gt;
      {todos.map(todo =&gt; (
        &lt;div key={todo.id}&gt;
          &lt;input 
            type=&quot;checkbox&quot; 
            checked={todo.completed}
            onChange={() =&gt; toggleTodo(todo.id)}
          /&gt;
          &lt;span style={{ 
            textDecoration: todo.completed ? &#39;line-through&#39; : &#39;none&#39; 
          }}&gt;
            {todo.text}
          &lt;/span&gt;
          &lt;button onClick={() =&gt; deleteTodo(todo.id)}&gt;削除&lt;/button&gt;
        &lt;/div&gt;
      ))}
    &lt;/div&gt;
  );
}</code></pre></div>



<h3 class="wp-block-heading">オブジェクトの状態管理</h3>



<p class="is-style-icon_pen">オブジェクトの状態を更新する際も、元のオブジェクトを変更せずに新しいオブジェクトを作成します。</p>



<div class="hcb_wrap"><pre class="prism line-numbers lang-js" data-lang="JavaScript"><code>function UserProfile() {
  const [user, setUser] = useState({
    name: &quot;田中太郎&quot;,
    age: 25,
    email: &quot;tanaka@example.com&quot;
  });

  // 名前を更新
  const updateName = (newName) =&gt; {
    setUser(prevUser =&gt; ({
      ...prevUser, // 既存のプロパティをコピー
      name: newName // 名前のみ更新
    }));
  };

  // 年齢を更新
  const updateAge = (newAge) =&gt; {
    setUser(prevUser =&gt; ({
      ...prevUser,
      age: newAge
    }));
  };

  return (
    &lt;div&gt;
      &lt;p&gt;名前: {user.name}&lt;/p&gt;
      &lt;p&gt;年齢: {user.age}&lt;/p&gt;
      &lt;p&gt;メール: {user.email}&lt;/p&gt;
      &lt;button onClick={() =&gt; updateName(&quot;佐藤花子&quot;)}&gt;
        名前を変更
      &lt;/button&gt;
      &lt;button onClick={() =&gt; updateAge(30)}&gt;
        年齢を変更
      &lt;/button&gt;
    &lt;/div&gt;
  );
}</code></pre></div>



<h2 class="wp-block-heading">【実践】useStateを使った動的なTODOアプリ作成</h2>



<p class="is-style-bg_stripe">ここからは実際に手を動かして、useStateを使った動的なTODOアプリケーションを作成していきましょう。</p>



<h3 class="wp-block-heading">1. App.jsの修正</h3>



<p>既存の<code>src/App.js</code>を以下のように修正してください。</p>



<div class="hcb_wrap"><pre class="prism line-numbers lang-js" data-lang="JavaScript"><code>import React, { useState } from &#39;react&#39;;
import &#39;./App.css&#39;;
import TodoHeader from &#39;./TodoHeader&#39;;
import TodoList from &#39;./TodoList&#39;;

function App() {
  const [todos, setTodos] = useState([
    { id: 1, text: &quot;Reactを学ぶ&quot;, completed: false, priority: &quot;high&quot; },
    { id: 2, text: &quot;TODOアプリを作る&quot;, completed: true, priority: &quot;medium&quot; },
    { id: 3, text: &quot;データベース連携&quot;, completed: false, priority: &quot;low&quot; },
    { id: 4, text: &quot;デプロイする&quot;, completed: false, priority: &quot;medium&quot; }
  ]);

  const completedCount = todos.filter(todo =&gt; todo.completed).length;

  // TODOの完了状態を切り替える関数
  const toggleTodo = (id) =&gt; {
    setTodos(prevTodos =&gt; 
      prevTodos.map(todo =&gt; 
        todo.id === id 
          ? { ...todo, completed: !todo.completed }
          : todo
      )
    );
  };

  return (
    &lt;div className=&quot;App&quot;&gt;
      &lt;TodoHeader 
        title=&quot;React TODOアプリ&quot;
        totalCount={todos.length}
        completedCount={completedCount}
      /&gt;
      &lt;TodoList todos={todos} onToggle={toggleTodo} /&gt;
    &lt;/div&gt;
  );
}

export default App;</code></pre></div>



<h3 class="wp-block-heading">2. TodoList.jsの修正</h3>



<p>既存の<code>src/TodoList.js</code>を以下のように修正してください。</p>



<div class="hcb_wrap"><pre class="prism line-numbers lang-js" data-lang="JavaScript"><code>import React from &#39;react&#39;;
import TodoItem from &#39;./TodoItem&#39;;

function TodoList({ todos, onToggle }) {
  return (
    &lt;div className=&quot;todo-list&quot;&gt;
      {todos.map((todo) =&gt; (
        &lt;TodoItem 
          key={todo.id}
          id={todo.id}
          text={todo.text}
          completed={todo.completed}
          priority={todo.priority}
          onToggle={onToggle}
        /&gt;
      ))}
    &lt;/div&gt;
  );
}

export default TodoList;</code></pre></div>



<h3 class="wp-block-heading">3. TodoItem.jsの修正</h3>



<p>既存の<code>src/TodoItem.js</code>を以下のように修正してください。</p>



<div class="hcb_wrap"><pre class="prism line-numbers lang-js" data-lang="JavaScript"><code>import React from &#39;react&#39;;

function TodoItem({ id, text, completed, priority = &quot;medium&quot;, onToggle }) {
  return (
    &lt;div className={`todo-item priority-${priority}`}&gt;
      &lt;input 
        type=&quot;checkbox&quot; 
        checked={completed} 
        onChange={() =&gt; onToggle(id)}
      /&gt;
      &lt;span style={{ 
        textDecoration: completed ? &#39;line-through&#39; : &#39;none&#39; 
      }}&gt;
        {text}
      &lt;/span&gt;
    &lt;/div&gt;
  );
}

export default TodoItem;</code></pre></div>


<script async src="https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js?client=ca-pub-4374558503914683"
     crossorigin="anonymous"></script>
<!-- ディスプレイ【横長】 -->
<ins class="adsbygoogle"
     style="display:block"
     data-ad-client="ca-pub-4374558503914683"
     data-ad-slot="9744298852"
     data-ad-format="auto"
     data-full-width-responsive="true"></ins>
<script>
     (adsbygoogle = window.adsbygoogle || []).push({});
</script>



<h2 class="wp-block-heading">動作確認</h2>



<p>実装が完了したら、開発サーバーが起動している状態でブラウザを確認してください。以下の機能が動作することを確認できます。</p>


<div class="wp-block-image is-style-browser_mac size_xs">
<figure class="aligncenter size-full"><img decoding="async" width="1021" height="526" src="https://kekenta-it-blog.com/wp-content/uploads/2025/07/react_todo_series_03_01.jpg" alt="TODOアプリ（第３回：完成イメージ）" class="wp-image-15450" srcset="https://kekenta-it-blog.com/wp-content/uploads/2025/07/react_todo_series_03_01.jpg 1021w, https://kekenta-it-blog.com/wp-content/uploads/2025/07/react_todo_series_03_01-300x155.jpg 300w, https://kekenta-it-blog.com/wp-content/uploads/2025/07/react_todo_series_03_01-768x396.jpg 768w" sizes="(max-width: 1021px) 100vw, 1021px" /><figcaption class="wp-element-caption">TODOアプリ（第３回：完成イメージ）</figcaption></figure>
</div>


<div class="wp-block-group is-style-big_icon_good"><div class="wp-block-group__inner-container is-layout-constrained wp-block-group-is-layout-constrained">
<ul class="wp-block-list is-style-check_list -list-under-dashed">
<li>チェックボックスをクリックすると、TODOの完了状態が切り替わる</li>



<li>完了したTODOには取り消し線が表示される</li>



<li>統計情報（完了数、未完了数）がリアルタイムで更新される</li>
</ul>
</div></div>



<h2 class="wp-block-heading">FAQ</h2>



<dl class="swell-block-faq -icon-circle is-style-faq-border" data-q="fill-custom" data-a="fill-main">
<div class="swell-block-faq__item"><dt class="faq_q">useStateでエラーが発生する場合</dt><dd class="faq_a">
<p>以下の点を確認してください。</p>



<ol class="wp-block-list">
<li><code>import { useState } from 'react'</code>が正しく記述されているか</li>



<li>useStateの構文が正しいか：<code>const [state, setState] = useState(initialValue)</code></li>



<li>コンポーネントの最上位で呼び出しているか</li>
</ol>
</dd></div>



<div class="swell-block-faq__item"><dt class="faq_q">状態が更新されない場合</dt><dd class="faq_a">
<p>以下の点を確認してください。</p>



<ol class="wp-block-list">
<li>setState関数を正しく呼び出しているか</li>



<li>状態更新関数内で元の状態を変更していないか（イミュータブルな更新を心がける）</li>



<li>依存関係が正しく設定されているか</li>
</ol>
</dd></div>



<div class="swell-block-faq__item"><dt class="faq_q">配列の状態更新でエラーが発生する場合</dt><dd class="faq_a">
<p>以下の点を確認してください。</p>



<ol class="wp-block-list">
<li>元の配列を直接変更していないか（push、pop、spliceなどは避ける）</li>



<li>新しい配列を作成しているか（map、filter、spread演算子を使用）</li>



<li>keyプロパティが正しく設定されているか</li>
</ol>
</dd></div>



<div class="swell-block-faq__item"><dt class="faq_q">オブジェクトの状態更新でエラーが発生する場合</dt><dd class="faq_a">
<p>以下の点を確認してください。</p>



<ol class="wp-block-list">
<li>元のオブジェクトを直接変更していないか</li>



<li>spread演算子（<code>...</code>）を使用して新しいオブジェクトを作成しているか</li>



<li>プロパティ名が正しく記述されているか</li>
</ol>
</dd></div>



<div class="swell-block-faq__item"><dt class="faq_q">無限ループが発生する場合</dt><dd class="faq_a">
<p>以下の点を確認してください。</p>



<ol class="wp-block-list">
<li>状態更新関数が条件なしで呼び出されていないか</li>



<li>useEffect内で依存配列が正しく設定されているか</li>



<li>状態更新が無限に繰り返されていないか</li>
</ol>
</dd></div>



<div class="swell-block-faq__item"><dt class="faq_q">パフォーマンスの問題が発生する場合</dt><dd class="faq_a">
<p>以下の点を確認してください。</p>



<ol class="wp-block-list">
<li>不要な再レンダリングが発生していないか</li>



<li>大きな配列やオブジェクトを直接状態として使用していないか</li>



<li>状態更新が頻繁に発生していないか</li>
</ol>
</dd></div>



<div class="swell-block-faq__item"><dt class="faq_q">状態の初期値が正しく設定されない場合</dt><dd class="faq_a">
<p>以下の点を確認してください。</p>



<ol class="wp-block-list">
<li>useStateの引数に正しい初期値を渡しているか</li>



<li>初期値の型が期待する型と一致しているか</li>



<li>初期値の計算が重い処理になっていないか</li>
</ol>
</dd></div>
</dl>


<script async src="https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js?client=ca-pub-4374558503914683"
     crossorigin="anonymous"></script>
<!-- ディスプレイ【横長】 -->
<ins class="adsbygoogle"
     style="display:block"
     data-ad-client="ca-pub-4374558503914683"
     data-ad-slot="9744298852"
     data-ad-format="auto"
     data-full-width-responsive="true"></ins>
<script>
     (adsbygoogle = window.adsbygoogle || []).push({});
</script>



<h2 class="wp-block-heading">まとめ</h2>



<p>今回は、<strong>Reactでの状態管理の基礎</strong>について学習しました。</p>



<p>useStateフックを使うことで、コンポーネント内でデータを保持し、そのデータが変更されたときに自動的にUIを更新することができるようになりました。</p>



<p>配列やオブジェクトの状態管理では、元のデータを変更せずに新しいデータを作成するという重要な原則を学びました。</p>


<div class="swell-block-balloon"><div class="c-balloon -bln-left" data-col="gray"><div class="c-balloon__icon -circle"><img decoding="async" src="data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==" data-src="https://kekenta-it-blog.com/wp-content/uploads/2023/07/キリッ-150x150.jpg" alt="" class="lazyload c-balloon__iconImg" width="80px" height="80px"><noscript><img decoding="async" src="https://kekenta-it-blog.com/wp-content/uploads/2023/07/キリッ-150x150.jpg" alt="" class="c-balloon__iconImg" width="80px" height="80px"></noscript><span class="c-balloon__iconName">ケケンタ</span></div><div class="c-balloon__body -speaking -border-on"><div class="c-balloon__text">
<p>次回は、イベントハンドリングとフォーム処理について学習していきます。ユーザーの入力を受け取り、TODOアプリに新しい機能を追加していきましょう！</p>
<span class="c-balloon__shapes"><span class="c-balloon__before"></span><span class="c-balloon__after"></span></span></div></div></div></div>


<p>この記事が少しでもお役に立ったなら何よりです。次回もお楽しみに！</p>


<div class="swell-block-postLink">			<div class="p-blogCard -internal" data-type="type2" data-onclick="clickLink">
				<div class="p-blogCard__inner">
					<span class="p-blogCard__caption">次の記事</span>
					<div class="p-blogCard__thumb c-postThumb"><figure class="c-postThumb__figure"><img decoding="async" src="https://kekenta-it-blog.com/wp-content/uploads/2025/07/eye-catch__react-event-handling-form-processing__15483-300x169.jpg" alt="" class="c-postThumb__img u-obf-cover" width="320" height="180"></figure></div>					<div class="p-blogCard__body">
						<a class="p-blogCard__title" href="https://kekenta-it-blog.com/react-event-handling-form-processing/">【React×TODOアプリ】イベントハンドリングとフォーム処理【基本編：第4回】</a>
											</div>
				</div>
			</div>
		</div>

<div class="p-blogParts post_content" data-partsID="15579">
<hr class="wp-block-separator has-alpha-channel-opacity"/>



<p class="is-style-balloon_box"><span style="--the-icon-svg: url(data:image/svg+xml;base64,PHN2ZyBoZWlnaHQ9IjFlbSIgd2lkdGg9IjFlbSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiBhcmlhLWhpZGRlbj0idHJ1ZSIgdmlld0JveD0iMCAwIDQ4IDQ4Ij48cGF0aCBkPSJNMTEuNyAxLjQgNi44IDVjLS41LjQtLjggMS0uOCAxLjZ2MjguN2MwIC44LjUgMS41IDEuMiAxLjhsMjQgMTAuM2MxLjMuNiAyLjgtLjQgMi44LTEuOFYxOWMwLS44LS41LTEuNS0xLjItMS44TDEwLjIgNy41bDIuOS0yLjJjLjktLjYgMi0uOCAzLS40bDIwLjYgOC44Yy43LjMgMS4yIDEgMS4yIDEuOFY0Mi45YzAgLjkgMSAxLjMgMS43LjhsMS43LTEuNWMuNC0uNC43LS45LjctMS41VjEzYzAtLjgtLjUtMS41LTEuMi0xLjhMMTYuNy44Yy0xLjctLjctMy42LS41LTUgLjZ6Ij48L3BhdGg+PC9zdmc+)" data-icon="LsBook" data-id="0" aria-hidden="true" class="swl-inline-icon">  </span> <strong>僕が実際にReact学習に使用した書籍です</strong></p>


<div id="rinkerid15577" class="yyi-rinker-contents  yyi-rinker-postid-15577 yyi-rinker-img-m yyi-rinker-catid-256 ">
	<div class="yyi-rinker-box">
		<div class="yyi-rinker-image">
							<a href="https://www.amazon.co.jp/dp/B09BV2HGN3?tag=kekenta03am0b-22&#038;linkCode=ogi&#038;th=1&#038;psc=1" rel="nofollow" class="yyi-rinker-tracking"  data-click-tracking="amazon_img 15577 モダンJavaScriptの基本から始める　React実践の教科書　（最新ReactHooks対応）" data-vars-click-id="amazon_img 15577 モダンJavaScriptの基本から始める　React実践の教科書　（最新ReactHooks対応）"><img decoding="async" src="https://m.media-amazon.com/images/I/51Y0-P+m94L._SL160_.jpg"  width="112" height="160" class="yyi-rinker-main-img" style="border: none;"></a>					</div>
		<div class="yyi-rinker-info">
			<div class="yyi-rinker-title">
									<a href="https://www.amazon.co.jp/dp/B09BV2HGN3?tag=kekenta03am0b-22&#038;linkCode=ogi&#038;th=1&#038;psc=1" rel="nofollow" class="yyi-rinker-tracking" data-click-tracking="amazon_title 15577 モダンJavaScriptの基本から始める　React実践の教科書　（最新ReactHooks対応）" data-vars-amp-click-id="amazon_title 15577 モダンJavaScriptの基本から始める　React実践の教科書　（最新ReactHooks対応）" >モダンJavaScriptの基本から始める　React実践の教科書　（最新ReactHooks対応）</a>							</div>
			<div class="yyi-rinker-detail">
							<div class="credit-box">created by&nbsp;<a href="https://oyakosodate.com/rinker/" rel="nofollow noopener" target="_blank" >Rinker</a></div>
										<div class="price-box">
							</div>
						</div>
						<ul class="yyi-rinker-links">
																	<li class="amazonkindlelink">
						<a href="https://www.amazon.co.jp/dp/B09BV2HGN3?tag=kekenta03am0b-22&amp;linkCode=ogi&amp;th=1&amp;psc=1" rel="nofollow" class="yyi-rinker-link yyi-rinker-tracking"  data-click-tracking="amazon_kindle 15577 モダンJavaScriptの基本から始める　React実践の教科書　（最新ReactHooks対応）"  data-vars-amp-click-id="amazon_kindle 15577 モダンJavaScriptの基本から始める　React実践の教科書　（最新ReactHooks対応）">Kindle</a>					</li>
								                    <li class="amazonlink">
						<a href="https://www.amazon.co.jp/dp/B09BV2HGN3?tag=kekenta03am0b-22&amp;linkCode=ogi&amp;th=1&amp;psc=1" rel="nofollow" class="yyi-rinker-link yyi-rinker-tracking"  data-click-tracking="amazon 15577 モダンJavaScriptの基本から始める　React実践の教科書　（最新ReactHooks対応）"  data-vars-amp-click-id="amazon 15577 モダンJavaScriptの基本から始める　React実践の教科書　（最新ReactHooks対応）">Amazon</a>					</li>
													<li class="rakutenlink">
						<a href="https://hb.afl.rakuten.co.jp/hgc/3ace225e.aaf54072.3ace225f.2cf27f19/Rinker_o_20250722203529?pc=https%3A%2F%2Fsearch.rakuten.co.jp%2Fsearch%2Fmall%2F%25E3%2583%25A2%25E3%2583%2580%25E3%2583%25B3JavaScript%25E3%2581%25AE%25E5%259F%25BA%25E6%259C%25AC%25E3%2581%258B%25E3%2582%2589%25E5%25A7%258B%25E3%2582%2581%25E3%2582%258B%25E3%2580%2580React%25E5%25AE%259F%25E8%25B7%25B5%25E3%2581%25AE%25E6%2595%2599%25E7%25A7%2591%25E6%259B%25B8%25E3%2580%2580%25EF%25BC%2588%25E6%259C%2580%25E6%2596%25B0ReactHooks%25E5%25AF%25BE%25E5%25BF%259C%25EF%25BC%2589%2F%3Ff%3D1%26grp%3Dproduct&amp;m=https%3A%2F%2Fsearch.rakuten.co.jp%2Fsearch%2Fmall%2F%25E3%2583%25A2%25E3%2583%2580%25E3%2583%25B3JavaScript%25E3%2581%25AE%25E5%259F%25BA%25E6%259C%25AC%25E3%2581%258B%25E3%2582%2589%25E5%25A7%258B%25E3%2582%2581%25E3%2582%258B%25E3%2580%2580React%25E5%25AE%259F%25E8%25B7%25B5%25E3%2581%25AE%25E6%2595%2599%25E7%25A7%2591%25E6%259B%25B8%25E3%2580%2580%25EF%25BC%2588%25E6%259C%2580%25E6%2596%25B0ReactHooks%25E5%25AF%25BE%25E5%25BF%259C%25EF%25BC%2589%2F%3Ff%3D1%26grp%3Dproduct" rel="nofollow" class="yyi-rinker-link yyi-rinker-tracking"  data-click-tracking="rakuten 15577 モダンJavaScriptの基本から始める　React実践の教科書　（最新ReactHooks対応）"  data-vars-amp-click-id="rakuten 15577 モダンJavaScriptの基本から始める　React実践の教科書　（最新ReactHooks対応）">楽天市場</a>					</li>
								                											</ul>
					</div>
	</div>
</div>
</div>
]]></content:encoded>
					
					<wfw:commentRss>https://kekenta-it-blog.com/react-state-management-usestate/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>【React×TODOアプリ】コンポーネントとJSXの理解【基本編：第2回】</title>
		<link>https://kekenta-it-blog.com/react-components-jsx-understanding/</link>
					<comments>https://kekenta-it-blog.com/react-components-jsx-understanding/#respond</comments>
		
		<dc:creator><![CDATA[ケケンタ]]></dc:creator>
		<pubDate>Mon, 21 Jul 2025 06:39:29 +0000</pubDate>
				<category><![CDATA[React]]></category>
		<category><![CDATA[Javascript]]></category>
		<category><![CDATA[TODOアプリ]]></category>
		<category><![CDATA[開発シリーズ]]></category>
		<guid isPermaLink="false">https://kekenta-it-blog.com/?p=15432</guid>

					<description><![CDATA[<p><img src="https://kekenta-it-blog.com/wp-content/uploads/2025/07/eye-catch__react-components-jsx-understanding__15432-1024x576.jpg" class="webfeedsFeaturedVisual" /></p>Reactで作るTODOアプリ開発シリーズ第２回 この記事では ReactのコンポーネントとJSX について詳しく学習していきます。 前回は、Reactの基礎知識と開発環境の構築について学習しました。今回は、Reactの [&#8230;]]]></description>
										<content:encoded><![CDATA[<p><img src="https://kekenta-it-blog.com/wp-content/uploads/2025/07/eye-catch__react-components-jsx-understanding__15432-1024x576.jpg" class="webfeedsFeaturedVisual" /></p>
<p><strong>Reactで作るTODOアプリ開発シリーズ第２回</strong></p>



<p>この記事では</p>



<p class="has-text-align-center is-style-big_kakko_box"><strong>ReactのコンポーネントとJSX</strong></p>



<p>について詳しく学習していきます。</p>


<div class="swell-block-postLink">			<div class="p-blogCard -internal" data-type="type2" data-onclick="clickLink">
				<div class="p-blogCard__inner">
					<span class="p-blogCard__caption">前回の記事</span>
					<div class="p-blogCard__thumb c-postThumb"><figure class="c-postThumb__figure"><img decoding="async" src="https://kekenta-it-blog.com/wp-content/uploads/2025/07/eye-catch__react-todo-app-development-basics__15419-300x169.jpg" alt="" class="c-postThumb__img u-obf-cover" width="320" height="180"></figure></div>					<div class="p-blogCard__body">
						<a class="p-blogCard__title" href="https://kekenta-it-blog.com/react-todo-app-development-basics/">【React×TODOアプリ】Reactの基礎と開発環境の準備【基本編：第1回】</a>
											</div>
				</div>
			</div>
		</div>


<p><a href="https://kekenta-it-blog.com/react-todo-app-development-basics/" data-type="post" data-id="15419">前回</a>は、<strong>Reactの基礎知識と開発環境の構築</strong>について学習しました。今回は、Reactの核となるコンポーネントとJSXについて、より深く理解していきましょう。</p>



<p>コンポーネントベース開発は、Reactの最大の特徴の一つです。小さな部品を組み合わせて大きなアプリケーションを作ることで、コードの再利用性と保守性を大幅に向上させることができます。</p>



<div class="swell-block-capbox cap_box"><div class="cap_box_ttl"><span><span data-icon="LsLightbulb" data-id="0" style="--the-icon-svg: url(data:image/svg+xml;base64,PHN2ZyBoZWlnaHQ9IjFlbSIgd2lkdGg9IjFlbSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiBhcmlhLWhpZGRlbj0idHJ1ZSIgdmlld0JveD0iMCAwIDQ4IDQ4Ij48cGF0aCBkPSJNMzIgNDYuNUgxNmMtMS4xIDAtMi0uOS0yLTJzLjktMiAyLTJoMTZjMS4xIDAgMiAuOSAyIDJzLS45IDItMiAyek00MS43IDE1LjlDNDEuMyAxMyA0MCAxMC4zIDM4LjIgOCAzNC41IDMuMiAyOSAuOCAyMy4xIDEgMTQgMS40IDYuNSA4LjkgNiAxOGMtLjMgNiAyLjQgMTEuNyA3LjIgMTUuNC41LjQuOC45LjggMS41djEuNmMwIDIuMiAxLjggNCA0IDRoMTJjMi4yIDAgNC0xLjggNC00VjM1YzAtLjYuMy0xLjIuOS0xLjcgNS4zLTQgOC0xMC42IDYuOC0xNy40em0tNy4xIDEuN2gtLjNjLS43IDAtMS4zLS41LTEuNS0xLjItLjctMy4yLTMuMi01LjctNi40LTYuMy0uOC0uMS0xLjQtLjktMS4yLTEuN3MuOS0xLjQgMS43LTEuMmM0LjQuOCA4IDQuMiA4LjkgOC42LjEuOC0uNCAxLjYtMS4yIDEuOHoiPjwvcGF0aD48L3N2Zz4=)" aria-hidden="true" class="swl-inline-icon"> </span> <strong>この記事でわかること</strong></span></div><div class="cap_box_content">
<ul class="wp-block-list is-style-check_list -list-under-dashed">
<li>コンポーネントの概念と種類（関数コンポーネント、クラスコンポーネント）</li>



<li>JSXの詳細な文法と特徴</li>



<li>Propsの受け渡し方法</li>



<li>コンポーネントの分割と再利用</li>



<li>簡単なTODOアイテムコンポーネントの作成</li>
</ul>
</div></div>


<div class="swell-block-balloon"><div class="c-balloon -bln-left" data-col="gray"><div class="c-balloon__icon -circle"><img decoding="async" src="data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==" data-src="https://kekenta-it-blog.com/wp-content/uploads/2023/07/キリッ-150x150.jpg" alt="" class="lazyload c-balloon__iconImg" width="80px" height="80px"><noscript><img decoding="async" src="https://kekenta-it-blog.com/wp-content/uploads/2023/07/キリッ-150x150.jpg" alt="" class="c-balloon__iconImg" width="80px" height="80px"></noscript><span class="c-balloon__iconName">ケケンタ</span></div><div class="c-balloon__body -speaking -border-on"><div class="c-balloon__text">
<p>コンポーネントベース開発の考え方を理解することで、より効率的で保守性の高いアプリケーションを作ることができるようになります！</p>
<span class="c-balloon__shapes"><span class="c-balloon__before"></span><span class="c-balloon__after"></span></span></div></div></div></div>

<div class="wp-block-image is-style-browser_mac size_xs">
<figure class="aligncenter size-full"><img decoding="async" width="1021" height="526" src="https://kekenta-it-blog.com/wp-content/uploads/2025/07/react_todo_series_02_01.jpg" alt="TODOアプリ（第２回：完成イメージ）" class="wp-image-15437" srcset="https://kekenta-it-blog.com/wp-content/uploads/2025/07/react_todo_series_02_01.jpg 1021w, https://kekenta-it-blog.com/wp-content/uploads/2025/07/react_todo_series_02_01-300x155.jpg 300w, https://kekenta-it-blog.com/wp-content/uploads/2025/07/react_todo_series_02_01-768x396.jpg 768w" sizes="(max-width: 1021px) 100vw, 1021px" /><figcaption class="wp-element-caption">TODOアプリ（第２回：完成イメージ）</figcaption></figure>
</div>


<p class="is-style-balloon_box"><span style="--the-icon-svg: url(data:image/svg+xml;base64,PHN2ZyBoZWlnaHQ9IjFlbSIgd2lkdGg9IjFlbSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiBhcmlhLWhpZGRlbj0idHJ1ZSIgdmlld0JveD0iMCAwIDQ4IDQ4Ij48cGF0aCBkPSJNMTAgM2gyOGMxLjEgMCAyIC45IDIgMnYzOS42YzAgLjktMS4xIDEuMy0xLjcuN0wyNCAzMSA5LjcgNDUuM2MtLjYuNi0xLjcuMi0xLjctLjdWNWMwLTEuMS45LTIgMi0yeiI+PC9wYXRoPjwvc3ZnPg==)" data-icon="LsBookmark" data-id="0" aria-hidden="true" class="swl-inline-icon"> </span> <strong>TODOアプリ開発シリーズのまとめ記事はこちら</strong></p>


<div class="swell-block-postLink">			<div class="p-blogCard -internal" data-type="type2" data-onclick="clickLink">
				<div class="p-blogCard__inner">
					<span class="p-blogCard__caption">シリーズ完全ガイド</span>
					<div class="p-blogCard__thumb c-postThumb"><figure class="c-postThumb__figure"><img decoding="async" src="https://kekenta-it-blog.com/wp-content/uploads/2025/07/eye-catch__react-todo-app-series-complete-guide-summary__15557-300x169.jpg" alt="" class="c-postThumb__img u-obf-cover" width="320" height="180"></figure></div>					<div class="p-blogCard__body">
						<a class="p-blogCard__title" href="https://kekenta-it-blog.com/react-todo-app-series-complete-guide-summary/">【React】初心者向けTODOアプリ開発シリーズ &#8211; 完全ガイドまとめ</a>
											</div>
				</div>
			</div>
		</div>


<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading">前回までのコード</h2>



<p>第1回で作成したコードを確認しましょう。以下のファイル構成になっています。</p>



<h3 class="wp-block-heading">ファイル構造</h3>



<div class="hcb_wrap"><pre class="prism line-numbers lang-plain"><code>todo-app/
├── src/
│   ├── App.js
│   ├── App.css
│   ├── TodoItem.js
│   └── index.js</code></pre></div>



<h3 class="wp-block-heading">App.js</h3>



<div class="hcb_wrap"><pre class="prism line-numbers lang-js" data-file="App.js" data-lang="JavaScript"><code>import React from &#39;react&#39;;
import &#39;./App.css&#39;;
import TodoItem from &#39;./TodoItem&#39;;

function App() {
  return (
    &lt;div className=&quot;App&quot;&gt;
      &lt;h1&gt;React TODOアプリ&lt;/h1&gt;
      &lt;div className=&quot;todo-list&quot;&gt;
        &lt;TodoItem text=&quot;Reactを学ぶ&quot; completed={false} /&gt;
        &lt;TodoItem text=&quot;TODOアプリを作る&quot; completed={true} /&gt;
        &lt;TodoItem text=&quot;データベース連携&quot; completed={false} /&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  );
}

export default App;</code></pre></div>



<h3 class="wp-block-heading">TodoItem.js</h3>



<div class="hcb_wrap"><pre class="prism line-numbers lang-js" data-file="TodoItem.js" data-lang="JavaScript"><code>import React from &#39;react&#39;;

function TodoItem({ text, completed }) {
  return (
    &lt;div className=&quot;todo-item&quot;&gt;
      &lt;input 
        type=&quot;checkbox&quot; 
        checked={completed} 
        readOnly 
      /&gt;
      &lt;span style={{ 
        textDecoration: completed ? &#39;line-through&#39; : &#39;none&#39; 
      }}&gt;
        {text}
      &lt;/span&gt;
    &lt;/div&gt;
  );
}

export default TodoItem;</code></pre></div>



<h3 class="wp-block-heading">App.css</h3>



<div class="hcb_wrap"><pre class="prism line-numbers lang-js" data-file="App.css" data-lang="JavaScript"><code>.App {
  text-align: center;
  padding: 20px;
  max-width: 600px;
  margin: 0 auto;
}

.todo-list {
  margin-top: 20px;
}

.todo-item {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 10px;
  padding: 10px;
  border-bottom: 1px solid #eee;
}

.todo-item input[type=&quot;checkbox&quot;] {
  margin-right: 10px;
}

.todo-item span {
  font-size: 16px;
}</code></pre></div>


<script async src="https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js?client=ca-pub-4374558503914683"
     crossorigin="anonymous"></script>
<!-- ディスプレイ【横長】 -->
<ins class="adsbygoogle"
     style="display:block"
     data-ad-client="ca-pub-4374558503914683"
     data-ad-slot="9744298852"
     data-ad-format="auto"
     data-full-width-responsive="true"></ins>
<script>
     (adsbygoogle = window.adsbygoogle || []).push({});
</script>



<h2 class="wp-block-heading">コンポーネントの概念</h2>



<p class="is-style-bg_stripe">実際に手を動かす前に、まずは必要な知識について解説をしていきます。</p>



<p>Reactのコンポーネントは、UIを構成する独立した部品です。HTMLの要素を拡張したようなもので、独自のロジックとスタイルを持つことができます。</p>



<h3 class="wp-block-heading">コンポーネントの種類</h3>



<p>Reactには主に<strong>2種類</strong>のコンポーネントがあります：</p>



<h4 class="wp-block-heading">1. 関数コンポーネント（Function Component）</h4>



<p>現在のReactでは、関数コンポーネントが推奨されています。シンプルで理解しやすく、Hooksを使用して状態管理も行えます。</p>



<div class="hcb_wrap"><pre class="prism line-numbers lang-js" data-lang="JavaScript"><code>function Welcome({ name }) {
  return &lt;h1&gt;Hello, {name}!&lt;/h1&gt;;
}</code></pre></div>



<h4 class="wp-block-heading">2. クラスコンポーネント（Class Component）</h4>



<p>こちらは従来の書き方で、現在は関数コンポーネントが主流ですが、理解しておくと良いでしょう。</p>



<div class="hcb_wrap"><pre class="prism line-numbers lang-js" data-lang="JavaScript"><code>class Welcome extends React.Component {
  render() {
    return &lt;h1&gt;Hello, {this.props.name}!&lt;/h1&gt;;
  }
}</code></pre></div>



<h2 class="wp-block-heading">JSXの詳細な文法ルール</h2>



<p><strong>JSX</strong>は、<strong>JavaScriptの中にHTMLライクな記法を書くことができるReactの拡張構文</strong>です。</p>



<h3 class="wp-block-heading">1. 要素のネスト</h3>



<p>JSXでは、複数の要素を返す場合は、必ず1つの親要素で囲む必要があります。</p>



<div class="hcb_wrap"><pre class="prism line-numbers lang-js" data-lang="JavaScript"><code>// ❌ エラー：複数の要素を直接返している
function App() {
  return (
    &lt;h1&gt;タイトル&lt;/h1&gt;
    &lt;p&gt;説明文&lt;/p&gt;
  );
}

// ✅ 正しい：1つの親要素で囲んでいる
function App() {
  return (
    &lt;div&gt;
      &lt;h1&gt;タイトル&lt;/h1&gt;
      &lt;p&gt;説明文&lt;/p&gt;
    &lt;/div&gt;
  );
}

// ✅ Fragmentを使用する方法（推奨）
function App() {
  return (
    &lt;&gt;
      &lt;h1&gt;タイトル&lt;/h1&gt;
      &lt;p&gt;説明文&lt;/p&gt;
    &lt;/&gt;
  );
}</code></pre></div>



<h3 class="wp-block-heading">2. JavaScript式の埋め込み</h3>



<p>JSXの中では、<code>{}</code>を使ってJavaScriptの式を埋め込むことができます。</p>



<div class="hcb_wrap"><pre class="prism line-numbers lang-js" data-lang="JavaScript"><code>function App() {
  const name = &quot;React&quot;;
  const isLoggedIn = true;
  const items = [&quot;アイテム1&quot;, &quot;アイテム2&quot;, &quot;アイテム3&quot;];

  return (
    &lt;div&gt;
      &lt;h1&gt;Hello, {name}!&lt;/h1&gt;
      &lt;p&gt;{isLoggedIn ? &quot;ログイン中&quot; : &quot;ログアウト中&quot;}&lt;/p&gt;
      &lt;ul&gt;
        {items.map((item, index) =&gt; (
          &lt;li key={index}&gt;{item}&lt;/li&gt;
        ))}
      &lt;/ul&gt;
    &lt;/div&gt;
  );
}</code></pre></div>



<h3 class="wp-block-heading">3. 属性の書き方</h3>



<p>JSXでは、HTMLの属性名が少し異なります。</p>



<div class="hcb_wrap"><pre class="prism line-numbers lang-js" data-lang="JavaScript"><code>function App() {
  const className = &quot;container&quot;;
  const style = { backgroundColor: &quot;blue&quot;, color: &quot;white&quot; };

  return (
    &lt;div 
      className={className}  // classではなくclassName
      style={style}         // オブジェクトとして渡す
      data-testid=&quot;app&quot;     // カスタム属性はそのまま
    &gt;
      コンテンツ
    &lt;/div&gt;
  );
}</code></pre></div>


<script async src="https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js?client=ca-pub-4374558503914683"
     crossorigin="anonymous"></script>
<!-- ディスプレイ【横長】 -->
<ins class="adsbygoogle"
     style="display:block"
     data-ad-client="ca-pub-4374558503914683"
     data-ad-slot="9744298852"
     data-ad-format="auto"
     data-full-width-responsive="true"></ins>
<script>
     (adsbygoogle = window.adsbygoogle || []).push({});
</script>



<h2 class="wp-block-heading">Propsの受け渡し</h2>



<p><strong>Props</strong>は、<strong>親コンポーネントから子コンポーネントにデータを渡すための仕組み</strong>です。</p>



<h3 class="wp-block-heading">Propsの基本</h3>



<div class="hcb_wrap"><pre class="prism line-numbers lang-js" data-lang="JavaScript"><code>// 親コンポーネント
function App() {
  return (
    &lt;div&gt;
      &lt;TodoItem text=&quot;買い物に行く&quot; completed={false} priority=&quot;high&quot; /&gt;
      &lt;TodoItem text=&quot;本を読む&quot; completed={true} priority=&quot;low&quot; /&gt;
    &lt;/div&gt;
  );
}

// 子コンポーネント
function TodoItem({ text, completed, priority }) {
  return (
    &lt;div className={`todo-item priority-${priority}`}&gt;
      &lt;input type=&quot;checkbox&quot; checked={completed} readOnly /&gt;
      &lt;span style={{ textDecoration: completed ? &#39;line-through&#39; : &#39;none&#39; }}&gt;
        {text}
      &lt;/span&gt;
    &lt;/div&gt;
  );
}</code></pre></div>



<h3 class="wp-block-heading">デフォルト値の設定</h3>



<p>Propsにデフォルト値を設定することで、値が渡されなかった場合の処理を書くことができます。</p>



<div class="hcb_wrap"><pre class="prism line-numbers lang-js" data-lang="JavaScript"><code>function TodoItem({ text, completed = false, priority = &quot;medium&quot; }) {
  return (
    &lt;div className={`todo-item priority-${priority}`}&gt;
      &lt;input type=&quot;checkbox&quot; checked={completed} readOnly /&gt;
      &lt;span style={{ textDecoration: completed ? &#39;line-through&#39; : &#39;none&#39; }}&gt;
        {text}
      &lt;/span&gt;
    &lt;/div&gt;
  );
}</code></pre></div>



<p class="is-style-icon_pen">style属性の指定にはjavascriptの三項演算子を利用して条件分岐しています。</p>



<h3 class="wp-block-heading">スプレッド構文の使用</h3>



<p>スプレッド構文を使用することで、オブジェクトのプロパティを展開して渡すことができます。</p>



<div class="hcb_wrap"><pre class="prism line-numbers lang-js" data-lang="JavaScript"><code>function App() {
  const todoData = {
    text: &quot;買い物に行く&quot;,
    completed: false,
    priority: &quot;high&quot;,
    createdAt: &quot;2024-01-01&quot;
  };

  return (
    &lt;div&gt;
      &lt;TodoItem {...todoData} /&gt;
    &lt;/div&gt;
  );
}</code></pre></div>



<h2 class="wp-block-heading">【実践】コンポーネントの分割と再利用</h2>



<p class="is-style-bg_stripe">それでは、ここからは実際に手を動かして、新しいコンポーネントを作成していきましょう。</p>



<p>大きなコンポーネントを小さな部品に分割することで、コードの再利用性と保守性を向上させることができます。</p>



<h3 class="wp-block-heading">1. TodoListコンポーネントの作成</h3>



<p><code>src/TodoList.js</code>ファイルを新規作成し、以下のコードを記述してください。</p>



<div class="hcb_wrap"><pre class="prism line-numbers lang-js" data-file="TodoList.js" data-lang="JavaScript"><code>import React from &#39;react&#39;;
import TodoItem from &#39;./TodoItem&#39;;

function TodoList({ todos }) {
  return (
    &lt;div className=&quot;todo-list&quot;&gt;
      {todos.map((todo, index) =&gt; (
        &lt;TodoItem 
          key={index}
          text={todo.text}
          completed={todo.completed}
          priority={todo.priority}
        /&gt;
      ))}
    &lt;/div&gt;
  );
}

export default TodoList;</code></pre></div>



<h3 class="wp-block-heading">2. TodoHeaderコンポーネントの作成</h3>



<p><code>src/TodoHeader.js</code>ファイルを新規作成し、以下のコードを記述してください。</p>



<div class="hcb_wrap"><pre class="prism line-numbers lang-js" data-file="TodoHeader.js" data-lang="JavaScript"><code>import React from &#39;react&#39;;

function TodoHeader({ title, totalCount, completedCount }) {
  return (
    &lt;div className=&quot;todo-header&quot;&gt;
      &lt;h1&gt;{title}&lt;/h1&gt;
      &lt;div className=&quot;todo-stats&quot;&gt;
        &lt;span&gt;総数: {totalCount}&lt;/span&gt;
        &lt;span&gt;完了: {completedCount}&lt;/span&gt;
        &lt;span&gt;未完了: {totalCount - completedCount}&lt;/span&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  );
}

export default TodoHeader;</code></pre></div>



<h3 class="wp-block-heading">3. App.jsの修正</h3>



<p>既存の<code>src/App.js</code>を以下のように修正してください。</p>



<div class="hcb_wrap"><pre class="prism line-numbers lang-js" data-file="App.js" data-lang="JavaScript"><code>import React from &#39;react&#39;;
import &#39;./App.css&#39;;
import TodoHeader from &#39;./TodoHeader&#39;;
import TodoList from &#39;./TodoList&#39;;

function App() {
  const todos = [
    { text: &quot;Reactを学ぶ&quot;, completed: false, priority: &quot;high&quot; },
    { text: &quot;TODOアプリを作る&quot;, completed: true, priority: &quot;medium&quot; },
    { text: &quot;データベース連携&quot;, completed: false, priority: &quot;low&quot; },
    { text: &quot;デプロイする&quot;, completed: false, priority: &quot;medium&quot; }
  ];

  const completedCount = todos.filter(todo =&gt; todo.completed).length;

  return (
    &lt;div className=&quot;App&quot;&gt;
      &lt;TodoHeader 
        title=&quot;React TODOアプリ&quot;
        totalCount={todos.length}
        completedCount={completedCount}
      /&gt;
      &lt;TodoList todos={todos} /&gt;
    &lt;/div&gt;
  );
}

export default App;</code></pre></div>



<h3 class="wp-block-heading">4. スタイルの追加</h3>



<p>既存の<code>src/App.css</code>に以下のスタイルを追加してください。</p>



<div class="hcb_wrap"><pre class="prism line-numbers lang-css" data-lang="CSS"><code>.todo-header {
  margin-bottom: 30px;
}

.todo-stats {
  display: flex;
  justify-content: center;
  gap: 20px;
  margin-top: 10px;
  font-size: 14px;
  color: #666;
}

.todo-stats span {
  padding: 5px 10px;
  background-color: #f5f5f5;
  border-radius: 15px;
}

.priority-high {
  border-left: 4px solid #ff4757;
}

.priority-medium {
  border-left: 4px solid #ffa502;
}

.priority-low {
  border-left: 4px solid #2ed573;
}</code></pre></div>



<h3 class="wp-block-heading">5. TodoItem.jsの更新</h3>



<p>既存の<code>src/TodoItem.js</code>を以下のように更新してください（priorityプロパティを追加）。</p>



<div class="hcb_wrap"><pre class="prism line-numbers lang-js" data-file="TodoItem.js" data-lang="JavaScript"><code>import React from &#39;react&#39;;

function TodoItem({ text, completed, priority = &quot;medium&quot; }) {
  return (
    &lt;div className={`todo-item priority-${priority}`}&gt;
      &lt;input 
        type=&quot;checkbox&quot; 
        checked={completed} 
        readOnly 
      /&gt;
      &lt;span style={{ 
        textDecoration: completed ? &#39;line-through&#39; : &#39;none&#39; 
      }}&gt;
        {text}
      &lt;/span&gt;
    &lt;/div&gt;
  );
}

export default TodoItem;</code></pre></div>



<h2 class="wp-block-heading">動作確認</h2>



<p>実装が完了したら、開発サーバーが起動している状態でブラウザを確認してください。以下のような表示が確認できます。</p>


<div class="wp-block-image is-style-browser_mac size_xs">
<figure class="aligncenter size-full"><img decoding="async" width="1021" height="526" src="https://kekenta-it-blog.com/wp-content/uploads/2025/07/react_todo_series_02_01.jpg" alt="TODOアプリ（第２回：完成イメージ）" class="wp-image-15437" srcset="https://kekenta-it-blog.com/wp-content/uploads/2025/07/react_todo_series_02_01.jpg 1021w, https://kekenta-it-blog.com/wp-content/uploads/2025/07/react_todo_series_02_01-300x155.jpg 300w, https://kekenta-it-blog.com/wp-content/uploads/2025/07/react_todo_series_02_01-768x396.jpg 768w" sizes="(max-width: 1021px) 100vw, 1021px" /><figcaption class="wp-element-caption">TODOアプリ（第２回：完成イメージ）</figcaption></figure>
</div>


<div class="wp-block-group has-border -border01 is-style-big_icon_good"><div class="wp-block-group__inner-container is-layout-constrained wp-block-group-is-layout-constrained">
<ul class="wp-block-list is-style-check_list -list-under-dashed">
<li>タイトルと統計情報（総数、完了数、未完了数）</li>



<li>優先度に応じた色分けされたTODOアイテム（左端の色付きボーダー）</li>
</ul>
</div></div>


<script async src="https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js?client=ca-pub-4374558503914683"
     crossorigin="anonymous"></script>
<!-- ディスプレイ【横長】 -->
<ins class="adsbygoogle"
     style="display:block"
     data-ad-client="ca-pub-4374558503914683"
     data-ad-slot="9744298852"
     data-ad-format="auto"
     data-full-width-responsive="true"></ins>
<script>
     (adsbygoogle = window.adsbygoogle || []).push({});
</script>



<h2 class="wp-block-heading">FAQ</h2>



<dl class="swell-block-faq -icon-circle is-style-faq-border" data-q="fill-custom" data-a="fill-main">
<div class="swell-block-faq__item"><dt class="faq_q">コンポーネントが表示されない場合</dt><dd class="faq_a">
<p>以下の点を確認してください。</p>



<ol class="wp-block-list">
<li>ファイル名とimport文が一致しているか</li>



<li>export defaultが正しく記述されているか</li>



<li>ファイルパスが正しいか</li>



<li>コンポーネント名が大文字で始まっているか</li>
</ol>
</dd></div>



<div class="swell-block-faq__item"><dt class="faq_q">Propsが正しく渡されていない場合</dt><dd class="faq_a">
<p>以下の点を確認してください。</p>



<ol class="wp-block-list">
<li>親コンポーネントでpropsを正しく渡しているか</li>



<li>子コンポーネントでpropsを正しく受け取っているか</li>



<li>プロパティ名が一致しているか</li>
</ol>
</dd></div>



<div class="swell-block-faq__item"><dt class="faq_q">JSXでエラーが発生する場合</dt><dd class="faq_a">
<p>以下の点を確認してください。</p>



<ol class="wp-block-list">
<li>すべての要素が一つの要素で囲まれているか</li>



<li>閉じタグが正しく記述されているか</li>



<li>className属性を使用しているか（classではない）</li>
</ol>
</dd></div>



<div class="swell-block-faq__item"><dt class="faq_q">条件付きレンダリングが動作しない場合</dt><dd class="faq_a">
<p>以下の点を確認してください。</p>



<ol class="wp-block-list">
<li>条件式が正しく記述されているか</li>



<li>三項演算子の構文が正しいか</li>



<li>条件に応じた要素が正しく返されているか</li>
</ol>
</dd></div>



<div class="swell-block-faq__item"><dt class="faq_q">スタイルが適用されない場合</dt><dd class="faq_a">
<p>以下の点を確認してください。</p>



<ol class="wp-block-list">
<li>CSSファイルが正しくimportされているか</li>



<li>クラス名が正しく記述されているか</li>



<li>CSSの優先度（詳細度）が適切か</li>
</ol>
</dd></div>



<div class="swell-block-faq__item"><dt class="faq_q">コンポーネントの分割で迷った場合</dt><dd class="faq_a">
<p>以下の原則を参考にしてください。</p>



<ol class="wp-block-list">
<li>単一責任の原則：一つのコンポーネントに一つの役割</li>



<li>再利用性：他の場所でも使えるか</li>



<li>保守性：変更しやすい構造か</li>
</ol>
</dd></div>
</dl>



<h2 class="wp-block-heading">まとめ</h2>



<p>今回は、ReactのコンポーネントとJSXについて詳しく学習しました。</p>



<p>コンポーネントベース開発により、UIを小さな部品に分割して開発することで、コードの再利用性と保守性を大幅に向上させることができます。</p>



<p>JSXの詳細な文法とPropsの受け渡し方法を理解することで、より柔軟で拡張性の高いコンポーネントを作成できるようになりました。</p>


<div class="swell-block-balloon"><div class="c-balloon -bln-left" data-col="gray"><div class="c-balloon__icon -circle"><img decoding="async" src="data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==" data-src="https://kekenta-it-blog.com/wp-content/uploads/2023/11/kekenta-icon-150x150.jpg" alt="" class="lazyload c-balloon__iconImg" width="80px" height="80px"><noscript><img decoding="async" src="https://kekenta-it-blog.com/wp-content/uploads/2023/11/kekenta-icon-150x150.jpg" alt="" class="c-balloon__iconImg" width="80px" height="80px"></noscript><span class="c-balloon__iconName">ケケンタ</span></div><div class="c-balloon__body -speaking -border-on"><div class="c-balloon__text">
<p>次回は、Reactでの状態管理について学習していきます。useStateフックを使って、動的なTODOアプリケーションを作成していきましょう！</p>
<span class="c-balloon__shapes"><span class="c-balloon__before"></span><span class="c-balloon__after"></span></span></div></div></div></div>


<p>この記事が少しでもお役に立ったなら何よりです。次回もお楽しみに！</p>


<div class="swell-block-postLink">			<div class="p-blogCard -internal" data-type="type2" data-onclick="clickLink">
				<div class="p-blogCard__inner">
					<span class="p-blogCard__caption">次の記事</span>
					<div class="p-blogCard__thumb c-postThumb"><figure class="c-postThumb__figure"><img decoding="async" src="https://kekenta-it-blog.com/wp-content/uploads/2025/07/eye-catch__react-state-management-usestate__15448-300x169.jpg" alt="" class="c-postThumb__img u-obf-cover" width="320" height="180"></figure></div>					<div class="p-blogCard__body">
						<a class="p-blogCard__title" href="https://kekenta-it-blog.com/react-state-management-usestate/">【React×TODOアプリ】状態管理の基礎 &#8211; useState【基本編：第3回】</a>
											</div>
				</div>
			</div>
		</div>

<div class="p-blogParts post_content" data-partsID="15579">
<hr class="wp-block-separator has-alpha-channel-opacity"/>



<p class="is-style-balloon_box"><span style="--the-icon-svg: url(data:image/svg+xml;base64,PHN2ZyBoZWlnaHQ9IjFlbSIgd2lkdGg9IjFlbSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiBhcmlhLWhpZGRlbj0idHJ1ZSIgdmlld0JveD0iMCAwIDQ4IDQ4Ij48cGF0aCBkPSJNMTEuNyAxLjQgNi44IDVjLS41LjQtLjggMS0uOCAxLjZ2MjguN2MwIC44LjUgMS41IDEuMiAxLjhsMjQgMTAuM2MxLjMuNiAyLjgtLjQgMi44LTEuOFYxOWMwLS44LS41LTEuNS0xLjItMS44TDEwLjIgNy41bDIuOS0yLjJjLjktLjYgMi0uOCAzLS40bDIwLjYgOC44Yy43LjMgMS4yIDEgMS4yIDEuOFY0Mi45YzAgLjkgMSAxLjMgMS43LjhsMS43LTEuNWMuNC0uNC43LS45LjctMS41VjEzYzAtLjgtLjUtMS41LTEuMi0xLjhMMTYuNy44Yy0xLjctLjctMy42LS41LTUgLjZ6Ij48L3BhdGg+PC9zdmc+)" data-icon="LsBook" data-id="0" aria-hidden="true" class="swl-inline-icon">  </span> <strong>僕が実際にReact学習に使用した書籍です</strong></p>


<div id="rinkerid15577" class="yyi-rinker-contents  yyi-rinker-postid-15577 yyi-rinker-img-m yyi-rinker-catid-256 ">
	<div class="yyi-rinker-box">
		<div class="yyi-rinker-image">
							<a href="https://www.amazon.co.jp/dp/B09BV2HGN3?tag=kekenta03am0b-22&#038;linkCode=ogi&#038;th=1&#038;psc=1" rel="nofollow" class="yyi-rinker-tracking"  data-click-tracking="amazon_img 15577 モダンJavaScriptの基本から始める　React実践の教科書　（最新ReactHooks対応）" data-vars-click-id="amazon_img 15577 モダンJavaScriptの基本から始める　React実践の教科書　（最新ReactHooks対応）"><img decoding="async" src="https://m.media-amazon.com/images/I/51Y0-P+m94L._SL160_.jpg"  width="112" height="160" class="yyi-rinker-main-img" style="border: none;"></a>					</div>
		<div class="yyi-rinker-info">
			<div class="yyi-rinker-title">
									<a href="https://www.amazon.co.jp/dp/B09BV2HGN3?tag=kekenta03am0b-22&#038;linkCode=ogi&#038;th=1&#038;psc=1" rel="nofollow" class="yyi-rinker-tracking" data-click-tracking="amazon_title 15577 モダンJavaScriptの基本から始める　React実践の教科書　（最新ReactHooks対応）" data-vars-amp-click-id="amazon_title 15577 モダンJavaScriptの基本から始める　React実践の教科書　（最新ReactHooks対応）" >モダンJavaScriptの基本から始める　React実践の教科書　（最新ReactHooks対応）</a>							</div>
			<div class="yyi-rinker-detail">
							<div class="credit-box">created by&nbsp;<a href="https://oyakosodate.com/rinker/" rel="nofollow noopener" target="_blank" >Rinker</a></div>
										<div class="price-box">
							</div>
						</div>
						<ul class="yyi-rinker-links">
																	<li class="amazonkindlelink">
						<a href="https://www.amazon.co.jp/dp/B09BV2HGN3?tag=kekenta03am0b-22&amp;linkCode=ogi&amp;th=1&amp;psc=1" rel="nofollow" class="yyi-rinker-link yyi-rinker-tracking"  data-click-tracking="amazon_kindle 15577 モダンJavaScriptの基本から始める　React実践の教科書　（最新ReactHooks対応）"  data-vars-amp-click-id="amazon_kindle 15577 モダンJavaScriptの基本から始める　React実践の教科書　（最新ReactHooks対応）">Kindle</a>					</li>
								                    <li class="amazonlink">
						<a href="https://www.amazon.co.jp/dp/B09BV2HGN3?tag=kekenta03am0b-22&amp;linkCode=ogi&amp;th=1&amp;psc=1" rel="nofollow" class="yyi-rinker-link yyi-rinker-tracking"  data-click-tracking="amazon 15577 モダンJavaScriptの基本から始める　React実践の教科書　（最新ReactHooks対応）"  data-vars-amp-click-id="amazon 15577 モダンJavaScriptの基本から始める　React実践の教科書　（最新ReactHooks対応）">Amazon</a>					</li>
													<li class="rakutenlink">
						<a href="https://hb.afl.rakuten.co.jp/hgc/3ace225e.aaf54072.3ace225f.2cf27f19/Rinker_o_20250722203529?pc=https%3A%2F%2Fsearch.rakuten.co.jp%2Fsearch%2Fmall%2F%25E3%2583%25A2%25E3%2583%2580%25E3%2583%25B3JavaScript%25E3%2581%25AE%25E5%259F%25BA%25E6%259C%25AC%25E3%2581%258B%25E3%2582%2589%25E5%25A7%258B%25E3%2582%2581%25E3%2582%258B%25E3%2580%2580React%25E5%25AE%259F%25E8%25B7%25B5%25E3%2581%25AE%25E6%2595%2599%25E7%25A7%2591%25E6%259B%25B8%25E3%2580%2580%25EF%25BC%2588%25E6%259C%2580%25E6%2596%25B0ReactHooks%25E5%25AF%25BE%25E5%25BF%259C%25EF%25BC%2589%2F%3Ff%3D1%26grp%3Dproduct&amp;m=https%3A%2F%2Fsearch.rakuten.co.jp%2Fsearch%2Fmall%2F%25E3%2583%25A2%25E3%2583%2580%25E3%2583%25B3JavaScript%25E3%2581%25AE%25E5%259F%25BA%25E6%259C%25AC%25E3%2581%258B%25E3%2582%2589%25E5%25A7%258B%25E3%2582%2581%25E3%2582%258B%25E3%2580%2580React%25E5%25AE%259F%25E8%25B7%25B5%25E3%2581%25AE%25E6%2595%2599%25E7%25A7%2591%25E6%259B%25B8%25E3%2580%2580%25EF%25BC%2588%25E6%259C%2580%25E6%2596%25B0ReactHooks%25E5%25AF%25BE%25E5%25BF%259C%25EF%25BC%2589%2F%3Ff%3D1%26grp%3Dproduct" rel="nofollow" class="yyi-rinker-link yyi-rinker-tracking"  data-click-tracking="rakuten 15577 モダンJavaScriptの基本から始める　React実践の教科書　（最新ReactHooks対応）"  data-vars-amp-click-id="rakuten 15577 モダンJavaScriptの基本から始める　React実践の教科書　（最新ReactHooks対応）">楽天市場</a>					</li>
								                											</ul>
					</div>
	</div>
</div>
</div>
]]></content:encoded>
					
					<wfw:commentRss>https://kekenta-it-blog.com/react-components-jsx-understanding/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>【React×TODOアプリ】Reactの基礎と開発環境の準備【基本編：第1回】</title>
		<link>https://kekenta-it-blog.com/react-todo-app-development-basics/</link>
					<comments>https://kekenta-it-blog.com/react-todo-app-development-basics/#respond</comments>
		
		<dc:creator><![CDATA[ケケンタ]]></dc:creator>
		<pubDate>Mon, 21 Jul 2025 06:37:55 +0000</pubDate>
				<category><![CDATA[React]]></category>
		<category><![CDATA[Javascript]]></category>
		<category><![CDATA[TODOアプリ]]></category>
		<category><![CDATA[開発シリーズ]]></category>
		<guid isPermaLink="false">https://kekenta-it-blog.com/?p=15419</guid>

					<description><![CDATA[<p><img src="https://kekenta-it-blog.com/wp-content/uploads/2025/07/eye-catch__react-todo-app-development-basics__15419-1024x576.jpg" class="webfeedsFeaturedVisual" /></p>Reactで作るTODOアプリ開発シリーズ第１回 それは早速ですが、シリーズ初投稿となる第１回では Reactの基礎知識と開発環境の構築方法 を解説します。 Reactは現在、Webアプリケーション開発で最も人気のあるJ [&#8230;]]]></description>
										<content:encoded><![CDATA[<p><img src="https://kekenta-it-blog.com/wp-content/uploads/2025/07/eye-catch__react-todo-app-development-basics__15419-1024x576.jpg" class="webfeedsFeaturedVisual" /></p>
<p><strong>Reactで作るTODOアプリ開発シリーズ第１回</strong></p>


<div class="swell-block-balloon"><div class="c-balloon -bln-left" data-col="gray"><div class="c-balloon__icon -circle"><img decoding="async" src="data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==" data-src="https://kekenta-it-blog.com/wp-content/uploads/2023/07/キリッ-150x150.jpg" alt="" class="lazyload c-balloon__iconImg" width="80px" height="80px"><noscript><img decoding="async" src="https://kekenta-it-blog.com/wp-content/uploads/2023/07/キリッ-150x150.jpg" alt="" class="c-balloon__iconImg" width="80px" height="80px"></noscript><span class="c-balloon__iconName">ケケンタ</span></div><div class="c-balloon__body -speaking -border-on"><div class="c-balloon__text">
<p>このシリーズでは、<strong>Reactの基礎から実践的なTODOアプリの開発まで、段階的に学習</strong>していきます。最終的には、基本編～発展編を経て、データベース連携まで行える本格的なアプリケーションを完成させることが目標です！</p>
<span class="c-balloon__shapes"><span class="c-balloon__before"></span><span class="c-balloon__after"></span></span></div></div></div></div>


<p>それは早速ですが、シリーズ初投稿となる<strong>第１回</strong>では</p>



<p class="has-text-align-center is-style-big_kakko_box"><strong>Reactの基礎知識と開発環境の構築方法</strong></p>



<p>を解説します。</p>



<p>Reactは現在、Webアプリケーション開発で最も人気のある<strong>JavaScriptライブラリ</strong>の一つです。Facebook（現Meta）が開発したこのライブラリは、コンポーネントベースの開発手法により、効率的で保守性の高いWebアプリケーションを作ることができます。</p>



<div class="swell-block-capbox cap_box"><div class="cap_box_ttl"><span><span data-icon="LsLightbulb" data-id="0" style="--the-icon-svg: url(data:image/svg+xml;base64,PHN2ZyBoZWlnaHQ9IjFlbSIgd2lkdGg9IjFlbSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiBhcmlhLWhpZGRlbj0idHJ1ZSIgdmlld0JveD0iMCAwIDQ4IDQ4Ij48cGF0aCBkPSJNMzIgNDYuNUgxNmMtMS4xIDAtMi0uOS0yLTJzLjktMiAyLTJoMTZjMS4xIDAgMiAuOSAyIDJzLS45IDItMiAyek00MS43IDE1LjlDNDEuMyAxMyA0MCAxMC4zIDM4LjIgOCAzNC41IDMuMiAyOSAuOCAyMy4xIDEgMTQgMS40IDYuNSA4LjkgNiAxOGMtLjMgNiAyLjQgMTEuNyA3LjIgMTUuNC41LjQuOC45LjggMS41djEuNmMwIDIuMiAxLjggNCA0IDRoMTJjMi4yIDAgNC0xLjggNC00VjM1YzAtLjYuMy0xLjIuOS0xLjcgNS4zLTQgOC0xMC42IDYuOC0xNy40em0tNy4xIDEuN2gtLjNjLS43IDAtMS4zLS41LTEuNS0xLjItLjctMy4yLTMuMi01LjctNi40LTYuMy0uOC0uMS0xLjQtLjktMS4yLTEuN3MuOS0xLjQgMS43LTEuMmM0LjQuOCA4IDQuMiA4LjkgOC42LjEuOC0uNCAxLjYtMS4yIDEuOHoiPjwvcGF0aD48L3N2Zz4=)" aria-hidden="true" class="swl-inline-icon"> </span> <strong>この記事でわかること</strong></span></div><div class="cap_box_content">
<ul class="wp-block-list -list-under-dashed is-style-check_list">
<li>Reactとは何か（仮想DOM、コンポーネントベース開発）</li>



<li>Node.jsとnpmのインストール方法</li>



<li>Create React Appでのプロジェクト作成</li>



<li>開発サーバーの起動と基本操作</li>



<li>JSXの基本文法</li>



<li>初めてのコンポーネント作成</li>
</ul>
</div></div>


<div class="wp-block-image is-style-browser_mac size_xs">
<figure class="aligncenter size-full"><img decoding="async" width="946" height="465" src="https://kekenta-it-blog.com/wp-content/uploads/2025/07/react_todo_series_01_02.jpg" alt="TODOアプリ（第１回：完成イメージ）" class="wp-image-15421" srcset="https://kekenta-it-blog.com/wp-content/uploads/2025/07/react_todo_series_01_02.jpg 946w, https://kekenta-it-blog.com/wp-content/uploads/2025/07/react_todo_series_01_02-300x147.jpg 300w, https://kekenta-it-blog.com/wp-content/uploads/2025/07/react_todo_series_01_02-768x378.jpg 768w" sizes="(max-width: 946px) 100vw, 946px" /><figcaption class="wp-element-caption">TODOアプリ（第１回：完成イメージ）</figcaption></figure>
</div>


<p class="is-style-balloon_box"><span style="--the-icon-svg: url(data:image/svg+xml;base64,PHN2ZyBoZWlnaHQ9IjFlbSIgd2lkdGg9IjFlbSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiBhcmlhLWhpZGRlbj0idHJ1ZSIgdmlld0JveD0iMCAwIDQ4IDQ4Ij48cGF0aCBkPSJNMTAgM2gyOGMxLjEgMCAyIC45IDIgMnYzOS42YzAgLjktMS4xIDEuMy0xLjcuN0wyNCAzMSA5LjcgNDUuM2MtLjYuNi0xLjcuMi0xLjctLjdWNWMwLTEuMS45LTIgMi0yeiI+PC9wYXRoPjwvc3ZnPg==)" data-icon="LsBookmark" data-id="0" aria-hidden="true" class="swl-inline-icon"> </span> <strong>TODOアプリ開発シリーズのまとめ記事はこちら</strong></p>


<div class="swell-block-postLink">			<div class="p-blogCard -internal" data-type="type2" data-onclick="clickLink">
				<div class="p-blogCard__inner">
					<span class="p-blogCard__caption">シリーズ完全ガイド</span>
					<div class="p-blogCard__thumb c-postThumb"><figure class="c-postThumb__figure"><img decoding="async" src="https://kekenta-it-blog.com/wp-content/uploads/2025/07/eye-catch__react-todo-app-series-complete-guide-summary__15557-300x169.jpg" alt="" class="c-postThumb__img u-obf-cover" width="320" height="180"></figure></div>					<div class="p-blogCard__body">
						<a class="p-blogCard__title" href="https://kekenta-it-blog.com/react-todo-app-series-complete-guide-summary/">【React】初心者向けTODOアプリ開発シリーズ &#8211; 完全ガイドまとめ</a>
											</div>
				</div>
			</div>
		</div>


<h2 class="wp-block-heading">Reactとは何か</h2>



<p>Reactは、<strong>ユーザーインターフェース（UI）を構築するためのJavaScriptライブラリ</strong>です。特に以下の特徴があります。</p>



<h3 class="wp-block-heading">仮想DOM（Virtual DOM）</h3>



<p>Reactの最大の特徴の一つが仮想DOMです。従来のWeb開発では、HTMLの要素を直接操作していましたが、Reactでは仮想的なDOMツリーを作成し、実際のDOMとの差分のみを更新します。</p>



<p>これにより、パフォーマンスが大幅に向上し、複雑なUIでもスムーズに動作するアプリケーションを作ることができます。</p>



<h3 class="wp-block-heading">コンポーネントベース開発</h3>



<p>Reactでは、UIを小さな部品（コンポーネント）に分割して開発します。例えば、TODOアプリであれば、</p>



<ul class="wp-block-list is-style-check_list -list-under-dashed">
<li>TodoList（TODOリスト全体）</li>



<li>TodoItem（個別のTODOアイテム）</li>



<li>TodoForm（TODO追加フォーム）</li>
</ul>



<p class="is-style-icon_good">このように分割することで、コードの再利用性が高まり、保守性も向上します。</p>


<script async src="https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js?client=ca-pub-4374558503914683"
     crossorigin="anonymous"></script>
<!-- ディスプレイ【横長】 -->
<ins class="adsbygoogle"
     style="display:block"
     data-ad-client="ca-pub-4374558503914683"
     data-ad-slot="9744298852"
     data-ad-format="auto"
     data-full-width-responsive="true"></ins>
<script>
     (adsbygoogle = window.adsbygoogle || []).push({});
</script>



<h2 class="wp-block-heading">開発環境の準備</h2>



<p class="is-style-bg_stripe">それではここからは実際に手を動かしていきましょう。まずはReactでTODOアプリ開発を行うための「開発環境の準備」からです。</p>



<h3 class="wp-block-heading">Node.jsのインストール</h3>



<p>Reactの開発には、<strong>Node.js</strong>が必要です。Node.jsは、JavaScriptをサーバーサイドで実行できるようにするプラットフォームです。</p>



<div class="swell-block-step is-style-small" data-num-style="circle">
<div class="swell-block-step__item"><div class="swell-block-step__number"><span class="__shape u-col-main" role="presentation"></span><span class="__label">STEP</span></div><div class="swell-block-step__title u-fz-m"><a href="https://nodejs.org/" target="_blank" rel="noreferrer noopener nofollow">Node.js公式サイト</a>にアクセス</div><div class="swell-block-step__body">

</div></div>



<div class="swell-block-step__item"><div class="swell-block-step__number"><span class="__shape u-col-main" role="presentation"></span><span class="__label">STEP</span></div><div class="swell-block-step__title u-fz-m">LTS版（推奨版）をダウンロード</div><div class="swell-block-step__body">

</div></div>



<div class="swell-block-step__item"><div class="swell-block-step__number"><span class="__shape u-col-main" role="presentation"></span><span class="__label">STEP</span></div><div class="swell-block-step__title u-fz-m">インストーラーを実行し、指示に従ってインストール</div><div class="swell-block-step__body">

</div></div>
</div>



<p>インストールが完了したら、ターミナル（コマンドプロンプト）を開いて、以下のコマンドを実行して確認します。</p>



<div class="hcb_wrap"><pre class="prism line-numbers lang-plain"><code>node --version
npm --version</code></pre></div>



<p class="is-style-icon_good">バージョン番号が表示されれば、インストールは成功です。</p>



<h3 class="wp-block-heading">Create React Appの使用</h3>



<p>Reactプロジェクトを作成する最も簡単な方法が、<strong>Create React App</strong>を使用することです。これは、Facebookが提供する公式のツールで、Reactアプリケーションの開発に必要な設定がすべて含まれています。</p>



<p>今回は、デスクトップ上でターミナルを開き、以下のコマンドを実行します。</p>



<div class="hcb_wrap"><pre class="prism line-numbers lang-plain"><code>npx create-react-app todo-app</code></pre></div>



<p>このコマンドにより、以下のファイル構造が自動的に作成されます。</p>



<p class="is-style-balloon_box u-mb-ctrl u-mb-10"><strong>コマンドで自動作成されるファイル構造</strong></p>



<div class="hcb_wrap"><pre class="prism line-numbers lang-plain"><code>todo-app/
├── node_modules/
├── public/
│   ├── index.html
│   └── favicon.ico
├── src/
│   ├── App.js
│   ├── App.css
│   ├── index.js
│   └── index.css
├── package.json
└── README.md</code></pre></div>



<h3 class="wp-block-heading">開発サーバーの起動</h3>



<p>次に、以下のコマンドでプロジェクトディレクトリに移動します。</p>



<div class="hcb_wrap"><pre class="prism line-numbers lang-plain"><code>cd todo-app</code></pre></div>



<p>続いて、以下のコマンドで開発サーバーを起動します。</p>



<div class="hcb_wrap"><pre class="prism line-numbers lang-plain"><code>npm start</code></pre></div>



<p>このコマンドを実行すると、ブラウザが自動的に開き、<code>http://localhost:3000</code>でReactアプリケーションが表示されます。</p>


<div class="wp-block-image is-style-browser_mac size_xs">
<figure class="aligncenter size-large"><img decoding="async" width="1024" height="635" src="https://kekenta-it-blog.com/wp-content/uploads/2025/07/react_todo_series_01_01-1024x635.jpg" alt="Reactアプリケーションの初期画面" class="wp-image-15422" srcset="https://kekenta-it-blog.com/wp-content/uploads/2025/07/react_todo_series_01_01-1024x635.jpg 1024w, https://kekenta-it-blog.com/wp-content/uploads/2025/07/react_todo_series_01_01-300x186.jpg 300w, https://kekenta-it-blog.com/wp-content/uploads/2025/07/react_todo_series_01_01-768x476.jpg 768w, https://kekenta-it-blog.com/wp-content/uploads/2025/07/react_todo_series_01_01.jpg 1045w" sizes="(max-width: 1024px) 100vw, 1024px" /><figcaption class="wp-element-caption">Reactアプリケーションの初期画面</figcaption></figure>
</div>


<h2 class="wp-block-heading">JSXの基本文法</h2>



<p class="is-style-bg_stripe">ここからはいったんReactで使用する文法について解説をしていきます。その後、実際に手を動かしてTODOアプリ開発の第一歩目を踏み出しましょう。</p>



<p><strong>JSX</strong>は、<strong>JavaScriptの中にHTMLライクな記法を書くことができるReactの拡張構文</strong>です。</p>



<h3 class="wp-block-heading">基本的なJSX</h3>



<div class="hcb_wrap"><pre class="prism line-numbers lang-js" data-lang="JavaScript"><code>function App() {
  return (
    &lt;div className=&quot;App&quot;&gt;
      &lt;h1&gt;Hello, React!&lt;/h1&gt;
      &lt;p&gt;これはJSXで書かれたコンポーネントです。&lt;/p&gt;
    &lt;/div&gt;
  );
}</code></pre></div>



<h3 class="wp-block-heading">JSXの特徴</h3>



<ol class="wp-block-list is-style-num_circle -list-under-dashed">
<li><strong>className属性</strong>: HTMLの<code>class</code>ではなく、<code>className</code>を使用</li>



<li><strong>閉じタグ</strong>: すべての要素は閉じタグが必要（<code>&lt;img /&gt;</code>のように自己終了タグも可能）</li>



<li><strong>JavaScript式の埋め込み</strong>: <code>{}</code>を使ってJavaScriptの式を埋め込むことが可能</li>
</ol>



<div class="hcb_wrap"><pre class="prism line-numbers lang-js" data-lang="JavaScript"><code>function App() {
  const name = &quot;React&quot;;
  const items = [&quot;アイテム1&quot;, &quot;アイテム2&quot;, &quot;アイテム3&quot;];

  return (
    &lt;div className=&quot;App&quot;&gt;
      &lt;h1&gt;Hello, {name}!&lt;/h1&gt;
      &lt;ul&gt;
        {items.map((item, index) =&gt; (
          &lt;li key={index}&gt;{item}&lt;/li&gt;
        ))}
      &lt;/ul&gt;
    &lt;/div&gt;
  );
}</code></pre></div>


<script async src="https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js?client=ca-pub-4374558503914683"
     crossorigin="anonymous"></script>
<!-- ディスプレイ【横長】 -->
<ins class="adsbygoogle"
     style="display:block"
     data-ad-client="ca-pub-4374558503914683"
     data-ad-slot="9744298852"
     data-ad-format="auto"
     data-full-width-responsive="true"></ins>
<script>
     (adsbygoogle = window.adsbygoogle || []).push({});
</script>



<h2 class="wp-block-heading">【実践】初めてのコンポーネント作成</h2>



<p class="is-style-bg_stripe">それでは、ここから実際に手を動かしてコンポーネントを作成してみましょう。<br>普段お使いのエディタでtodo-appディレクトリを開いたら、<code>src</code>フォルダ内に新しいファイルを作成します。</p>



<h3 class="wp-block-heading">1. TodoItemコンポーネントの作成</h3>



<p><code>src/TodoItem.js</code>ファイルを作成し、以下のコードを記述します。</p>



<div class="hcb_wrap"><pre class="prism line-numbers lang-js" data-file="TodoItem.js" data-lang="JavaScript"><code>import React from &#39;react&#39;;

function TodoItem({ text, completed }) {
  return (
    &lt;div className=&quot;todo-item&quot;&gt;
      &lt;input 
        type=&quot;checkbox&quot; 
        checked={completed} 
        readOnly 
      /&gt;
      &lt;span style={{ 
        textDecoration: completed ? &#39;line-through&#39; : &#39;none&#39; 
      }}&gt;
        {text}
      &lt;/span&gt;
    &lt;/div&gt;
  );
}

export default TodoItem;</code></pre></div>



<h3 class="wp-block-heading">2. App.jsの修正</h3>



<p><code>src/App.js</code>を以下のように修正します。</p>



<div class="hcb_wrap"><pre class="prism line-numbers lang-js" data-file="App.js" data-lang="JavaScript"><code>import React from &#39;react&#39;;
import &#39;./App.css&#39;;
import TodoItem from &#39;./TodoItem&#39;;

function App() {
  return (
    &lt;div className=&quot;App&quot;&gt;
      &lt;h1&gt;React TODOアプリ&lt;/h1&gt;
      &lt;div className=&quot;todo-list&quot;&gt;
        &lt;TodoItem text=&quot;Reactを学ぶ&quot; completed={false} /&gt;
        &lt;TodoItem text=&quot;TODOアプリを作る&quot; completed={true} /&gt;
        &lt;TodoItem text=&quot;データベース連携&quot; completed={false} /&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  );
}

export default App;</code></pre></div>



<h3 class="wp-block-heading">3. スタイルの追加</h3>



<p><code>src/App.css</code>に以下のスタイルを追加します。</p>



<div class="hcb_wrap"><pre class="prism line-numbers lang-css" data-file="App.css" data-lang="CSS"><code>.App {
  text-align: center;
  padding: 20px;
  max-width: 600px;
  margin: 0 auto;
}

.todo-list {
  margin-top: 20px;
}

.todo-item {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 10px;
  padding: 10px;
  border-bottom: 1px solid #eee;
}

.todo-item input[type=&quot;checkbox&quot;] {
  margin-right: 10px;
}

.todo-item span {
  font-size: 16px;
}</code></pre></div>



<h2 class="wp-block-heading">動作確認</h2>



<p>開発サーバーが起動している状態で、ブラウザを確認すると、以下のような表示が確認できます。</p>


<div class="wp-block-image is-style-browser_mac size_xs">
<figure class="aligncenter size-full"><img decoding="async" width="946" height="465" src="https://kekenta-it-blog.com/wp-content/uploads/2025/07/react_todo_series_01_02.jpg" alt="TODOアプリ（第１回：完成イメージ）" class="wp-image-15421" srcset="https://kekenta-it-blog.com/wp-content/uploads/2025/07/react_todo_series_01_02.jpg 946w, https://kekenta-it-blog.com/wp-content/uploads/2025/07/react_todo_series_01_02-300x147.jpg 300w, https://kekenta-it-blog.com/wp-content/uploads/2025/07/react_todo_series_01_02-768x378.jpg 768w" sizes="(max-width: 946px) 100vw, 946px" /><figcaption class="wp-element-caption">TODOアプリ（第１回：完成イメージ）</figcaption></figure>
</div>


<div class="wp-block-group is-style-big_icon_good"><div class="wp-block-group__inner-container is-layout-constrained wp-block-group-is-layout-constrained">
<ul class="wp-block-list is-style-check_list -list-under-dashed">
<li>「React TODOアプリ」というタイトル</li>



<li>3つのTODOアイテム（チェックボックス付き）</li>



<li>2番目のアイテムが完了状態（取り消し線付き）</li>
</ul>
</div></div>



<h2 class="wp-block-heading">発展課題</h2>



<p>基本を理解したら、ぜひ以下の課題に挑戦してみてください！</p>



<ol class="wp-block-list is-style-num_circle -list-under-dashed">
<li><strong>新しいTODOアイテムを追加する（ハードコーディングで）</strong></li>



<li><strong>アイテムの表示順序を変更する（ハードコーディングで）</strong></li>



<li><strong>異なるスタイルを適用する</strong></li>
</ol>


<script async src="https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js?client=ca-pub-4374558503914683"
     crossorigin="anonymous"></script>
<!-- ディスプレイ【横長】 -->
<ins class="adsbygoogle"
     style="display:block"
     data-ad-client="ca-pub-4374558503914683"
     data-ad-slot="9744298852"
     data-ad-format="auto"
     data-full-width-responsive="true"></ins>
<script>
     (adsbygoogle = window.adsbygoogle || []).push({});
</script>



<h2 class="wp-block-heading">FAQ</h2>



<dl class="swell-block-faq -icon-circle is-style-faq-border" data-q="fill-custom" data-a="fill-main">
<div class="swell-block-faq__item"><dt class="faq_q">Node.jsのインストールでエラーが発生した場合</dt><dd class="faq_a">
<p>Node.jsの公式サイトから最新版をダウンロードし直してください。Windowsの場合は管理者権限でインストールを実行し、インストール後にPCを再起動してください。</p>
</dd></div>



<div class="swell-block-faq__item"><dt class="faq_q"><code>npm start</code>でエラーが発生する場合</dt><dd class="faq_a">
<p>以下の手順を試してください。</p>



<ol class="wp-block-list">
<li><code>node_modules</code>フォルダを削除</li>



<li><code>npm install</code>を再実行</li>



<li><code>npm start</code>を実行</li>
</ol>
</dd></div>



<div class="swell-block-faq__item"><dt class="faq_q">ポート3000が既に使用されている場合</dt><dd class="faq_a">
<p>ターミナルで<code>Ctrl + C</code>で停止し、別のポートを使用するか、使用中のプロセスを終了してください。または、<code>npm start</code>の代わりに<code>PORT=3001 npm start</code>を実行してください。</p>
</dd></div>



<div class="swell-block-faq__item"><dt class="faq_q">JSXでエラーが発生する場合</dt><dd class="faq_a">
<p>JSXは必ず一つの要素で囲む必要があります。複数の要素がある場合は、<code>&lt;div&gt;</code>や<code>&lt;&gt;</code>（React Fragment）で囲んでください。</p>
</dd></div>



<div class="swell-block-faq__item"><dt class="faq_q">ブラウザでページが表示されない場合</dt><dd class="faq_a">
<p>ブラウザのキャッシュをクリアし、開発者ツールのコンソールでエラーメッセージを確認してください。また、URLが<code>http://localhost:3000</code>になっているか確認してください。</p>
</dd></div>



<div class="swell-block-faq__item"><dt class="faq_q">コンポーネントが表示されない場合</dt><dd class="faq_a">
<p>以下の点を確認してください。</p>



<ol class="wp-block-list">
<li>ファイル名とimport文が一致しているか</li>



<li>export defaultが正しく記述されているか</li>



<li>ファイルパスが正しいか</li>
</ol>
</dd></div>
</dl>



<h2 class="wp-block-heading">まとめ</h2>



<p>今回は、<strong>Reactの基礎知識と開発環境の構築</strong>について学習しました！</p>



<p>Reactは仮想DOMとコンポーネントベース開発により、効率的で保守性の高いWebアプリケーションを作ることができるJavaScriptライブラリです。</p>



<p>開発環境の準備から初めてのコンポーネント作成まで、実際に手を動かしながら学習することで、Reactの基本的な概念を理解することができました。</p>


<div class="swell-block-balloon"><div class="c-balloon -bln-left" data-col="gray"><div class="c-balloon__icon -circle"><img decoding="async" src="data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==" data-src="https://kekenta-it-blog.com/wp-content/uploads/2023/11/kekenta-icon-150x150.jpg" alt="" class="lazyload c-balloon__iconImg" width="80px" height="80px"><noscript><img decoding="async" src="https://kekenta-it-blog.com/wp-content/uploads/2023/11/kekenta-icon-150x150.jpg" alt="" class="c-balloon__iconImg" width="80px" height="80px"></noscript><span class="c-balloon__iconName">ケケンタ</span></div><div class="c-balloon__body -speaking -border-on"><div class="c-balloon__text">
<p>次回は、<strong>コンポーネントとJSX</strong>についてより詳しく学習していきます。コンポーネントの分割方法や、propsの受け渡しについて理解を深めていきましょう！</p>
<span class="c-balloon__shapes"><span class="c-balloon__before"></span><span class="c-balloon__after"></span></span></div></div></div></div>


<p>この記事が少しでもお役に立ったなら何よりです。次回もお楽しみに！</p>


<div class="swell-block-postLink">			<div class="p-blogCard -internal" data-type="type2" data-onclick="clickLink">
				<div class="p-blogCard__inner">
					<span class="p-blogCard__caption">次の記事</span>
					<div class="p-blogCard__thumb c-postThumb"><figure class="c-postThumb__figure"><img decoding="async" src="https://kekenta-it-blog.com/wp-content/uploads/2025/07/eye-catch__react-components-jsx-understanding__15432-300x169.jpg" alt="" class="c-postThumb__img u-obf-cover" width="320" height="180"></figure></div>					<div class="p-blogCard__body">
						<a class="p-blogCard__title" href="https://kekenta-it-blog.com/react-components-jsx-understanding/">【React×TODOアプリ】コンポーネントとJSXの理解【基本編：第2回】</a>
											</div>
				</div>
			</div>
		</div>

<div class="p-blogParts post_content" data-partsID="15579">
<hr class="wp-block-separator has-alpha-channel-opacity"/>



<p class="is-style-balloon_box"><span style="--the-icon-svg: url(data:image/svg+xml;base64,PHN2ZyBoZWlnaHQ9IjFlbSIgd2lkdGg9IjFlbSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiBhcmlhLWhpZGRlbj0idHJ1ZSIgdmlld0JveD0iMCAwIDQ4IDQ4Ij48cGF0aCBkPSJNMTEuNyAxLjQgNi44IDVjLS41LjQtLjggMS0uOCAxLjZ2MjguN2MwIC44LjUgMS41IDEuMiAxLjhsMjQgMTAuM2MxLjMuNiAyLjgtLjQgMi44LTEuOFYxOWMwLS44LS41LTEuNS0xLjItMS44TDEwLjIgNy41bDIuOS0yLjJjLjktLjYgMi0uOCAzLS40bDIwLjYgOC44Yy43LjMgMS4yIDEgMS4yIDEuOFY0Mi45YzAgLjkgMSAxLjMgMS43LjhsMS43LTEuNWMuNC0uNC43LS45LjctMS41VjEzYzAtLjgtLjUtMS41LTEuMi0xLjhMMTYuNy44Yy0xLjctLjctMy42LS41LTUgLjZ6Ij48L3BhdGg+PC9zdmc+)" data-icon="LsBook" data-id="0" aria-hidden="true" class="swl-inline-icon">  </span> <strong>僕が実際にReact学習に使用した書籍です</strong></p>


<div id="rinkerid15577" class="yyi-rinker-contents  yyi-rinker-postid-15577 yyi-rinker-img-m yyi-rinker-catid-256 ">
	<div class="yyi-rinker-box">
		<div class="yyi-rinker-image">
							<a href="https://www.amazon.co.jp/dp/B09BV2HGN3?tag=kekenta03am0b-22&#038;linkCode=ogi&#038;th=1&#038;psc=1" rel="nofollow" class="yyi-rinker-tracking"  data-click-tracking="amazon_img 15577 モダンJavaScriptの基本から始める　React実践の教科書　（最新ReactHooks対応）" data-vars-click-id="amazon_img 15577 モダンJavaScriptの基本から始める　React実践の教科書　（最新ReactHooks対応）"><img decoding="async" src="https://m.media-amazon.com/images/I/51Y0-P+m94L._SL160_.jpg"  width="112" height="160" class="yyi-rinker-main-img" style="border: none;"></a>					</div>
		<div class="yyi-rinker-info">
			<div class="yyi-rinker-title">
									<a href="https://www.amazon.co.jp/dp/B09BV2HGN3?tag=kekenta03am0b-22&#038;linkCode=ogi&#038;th=1&#038;psc=1" rel="nofollow" class="yyi-rinker-tracking" data-click-tracking="amazon_title 15577 モダンJavaScriptの基本から始める　React実践の教科書　（最新ReactHooks対応）" data-vars-amp-click-id="amazon_title 15577 モダンJavaScriptの基本から始める　React実践の教科書　（最新ReactHooks対応）" >モダンJavaScriptの基本から始める　React実践の教科書　（最新ReactHooks対応）</a>							</div>
			<div class="yyi-rinker-detail">
							<div class="credit-box">created by&nbsp;<a href="https://oyakosodate.com/rinker/" rel="nofollow noopener" target="_blank" >Rinker</a></div>
										<div class="price-box">
							</div>
						</div>
						<ul class="yyi-rinker-links">
																	<li class="amazonkindlelink">
						<a href="https://www.amazon.co.jp/dp/B09BV2HGN3?tag=kekenta03am0b-22&amp;linkCode=ogi&amp;th=1&amp;psc=1" rel="nofollow" class="yyi-rinker-link yyi-rinker-tracking"  data-click-tracking="amazon_kindle 15577 モダンJavaScriptの基本から始める　React実践の教科書　（最新ReactHooks対応）"  data-vars-amp-click-id="amazon_kindle 15577 モダンJavaScriptの基本から始める　React実践の教科書　（最新ReactHooks対応）">Kindle</a>					</li>
								                    <li class="amazonlink">
						<a href="https://www.amazon.co.jp/dp/B09BV2HGN3?tag=kekenta03am0b-22&amp;linkCode=ogi&amp;th=1&amp;psc=1" rel="nofollow" class="yyi-rinker-link yyi-rinker-tracking"  data-click-tracking="amazon 15577 モダンJavaScriptの基本から始める　React実践の教科書　（最新ReactHooks対応）"  data-vars-amp-click-id="amazon 15577 モダンJavaScriptの基本から始める　React実践の教科書　（最新ReactHooks対応）">Amazon</a>					</li>
													<li class="rakutenlink">
						<a href="https://hb.afl.rakuten.co.jp/hgc/3ace225e.aaf54072.3ace225f.2cf27f19/Rinker_o_20250722203529?pc=https%3A%2F%2Fsearch.rakuten.co.jp%2Fsearch%2Fmall%2F%25E3%2583%25A2%25E3%2583%2580%25E3%2583%25B3JavaScript%25E3%2581%25AE%25E5%259F%25BA%25E6%259C%25AC%25E3%2581%258B%25E3%2582%2589%25E5%25A7%258B%25E3%2582%2581%25E3%2582%258B%25E3%2580%2580React%25E5%25AE%259F%25E8%25B7%25B5%25E3%2581%25AE%25E6%2595%2599%25E7%25A7%2591%25E6%259B%25B8%25E3%2580%2580%25EF%25BC%2588%25E6%259C%2580%25E6%2596%25B0ReactHooks%25E5%25AF%25BE%25E5%25BF%259C%25EF%25BC%2589%2F%3Ff%3D1%26grp%3Dproduct&amp;m=https%3A%2F%2Fsearch.rakuten.co.jp%2Fsearch%2Fmall%2F%25E3%2583%25A2%25E3%2583%2580%25E3%2583%25B3JavaScript%25E3%2581%25AE%25E5%259F%25BA%25E6%259C%25AC%25E3%2581%258B%25E3%2582%2589%25E5%25A7%258B%25E3%2582%2581%25E3%2582%258B%25E3%2580%2580React%25E5%25AE%259F%25E8%25B7%25B5%25E3%2581%25AE%25E6%2595%2599%25E7%25A7%2591%25E6%259B%25B8%25E3%2580%2580%25EF%25BC%2588%25E6%259C%2580%25E6%2596%25B0ReactHooks%25E5%25AF%25BE%25E5%25BF%259C%25EF%25BC%2589%2F%3Ff%3D1%26grp%3Dproduct" rel="nofollow" class="yyi-rinker-link yyi-rinker-tracking"  data-click-tracking="rakuten 15577 モダンJavaScriptの基本から始める　React実践の教科書　（最新ReactHooks対応）"  data-vars-amp-click-id="rakuten 15577 モダンJavaScriptの基本から始める　React実践の教科書　（最新ReactHooks対応）">楽天市場</a>					</li>
								                											</ul>
					</div>
	</div>
</div>
</div>
]]></content:encoded>
					
					<wfw:commentRss>https://kekenta-it-blog.com/react-todo-app-development-basics/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
	</channel>
</rss>
