Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
Reactハンズオン資料~簡単なToDoアプリ作成~
Search
Masa
May 25, 2019
Programming
0
450
Reactハンズオン資料~簡単なToDoアプリ作成~
ToDoアプリの実装をしながら、
Reactのライフサイクルメソッドやstateに関する実装を学べるようなハンズオン資料です。
Masa
May 25, 2019
Tweet
Share
Other Decks in Programming
See All in Programming
안드로이드 9년차 개발자, 프론트엔드 주니어로 커리어 리셋하기
maryang
1
140
GISエンジニアから見たLINKSデータ
nokonoko1203
0
190
開発に寄りそう自動テストの実現
goyoki
2
1.5k
Navigating Dependency Injection with Metro
l2hyunwoo
1
190
実はマルチモーダルだった。ブラウザの組み込みAI🧠でWebの未来を感じてみよう #jsfes #gemini
n0bisuke2
3
1.3k
脳の「省エネモード」をデバッグする ~System 1(直感)と System 2(論理)の切り替え~
panda728
PRO
0
120
AtCoder Conference 2025「LLM時代のAHC」
imjk
2
600
ゲームの物理 剛体編
fadis
0
380
Cap'n Webについて
yusukebe
0
150
0→1 フロントエンド開発 Tips🚀 #レバテックMeetup
bengo4com
0
400
TerraformとStrands AgentsでAmazon Bedrock AgentCoreのSSO認証付きエージェントを量産しよう!
neruneruo
4
1.9k
Kotlin Multiplatform Meetup - Compose Multiplatform 외부 의존성 아키텍처 설계부터 운영까지
wisemuji
0
130
Featured
See All Featured
SEO Brein meetup: CTRL+C is not how to scale international SEO
lindahogenes
0
2.2k
コードの90%をAIが書く世界で何が待っているのか / What awaits us in a world where 90% of the code is written by AI
rkaga
57
40k
Introduction to Domain-Driven Design and Collaborative software design
baasie
1
520
Visual Storytelling: How to be a Superhuman Communicator
reverentgeek
2
400
It's Worth the Effort
3n
187
29k
Dealing with People You Can't Stand - Big Design 2015
cassininazir
367
27k
jQuery: Nuts, Bolts and Bling
dougneiner
65
8.3k
Leveraging Curiosity to Care for An Aging Population
cassininazir
1
130
Digital Ethics as a Driver of Design Innovation
axbom
PRO
0
130
[Rails World 2023 - Day 1 Closing Keynote] - The Magic of Rails
eileencodes
37
2.7k
Building an army of robots
kneath
306
46k
Bridging the Design Gap: How Collaborative Modelling removes blockers to flow between stakeholders and teams @FastFlow conf
baasie
0
410
Transcript
Reactハンズオン ~ ToDoアプリ作成 ~ @GeekStudio
自己紹介 ヤマダマサユキ(24) (@masaofyamad) Reactとfirebaseが好き 元Pear Inc. エンジニア 元Lyact Inc.
COO 現在:ヒモニート(フリーランスエンジニア ) 背景を考えながら ホームページ作ったり デザインをしたり システム作ったりするのが好きです。 いい写真を 探したけど 遠いのしか なかったです...
はじめに 環境 • nodeJSの動作環境 (npmのインストール) 知識 • HTML, CSSが扱える •
(JavaScriptの)変数や配列, イベントハンドリングなどについておおよそ理解してい る (理解する気持ちだけでも可)
Reactについて(おおざっぱ) • フロントエンド開発用のJavaScriptのライブラリ • 見えるところは全部できる (表示・ページ遷移・アニメーション) • React
Native(アプリ用)や、React VR(VR用)などの仲間がいる (構文が似ているので、すぐ慣れる) そして、HTML, CSSに比べて、とっても早い!
今回の目標 • 実際に作りながらReactの基本概要を理解する • 基本的なライフサイクルメソッドや、stateについて理解する
今回やらないこと • 直接実装に関係のないこと • 見た目を整えること • ホスティング
(サーバーを置いて、どの端末からでもアクセスできるようにすること) • データベース管理 ほんとに「Reactのみを扱います」
まずは、 今日の完成物をみてみましょう
目次 環境構築とアプリケーションの立ち上げ ページ遷移 ToDoリスト作成・追加 ToDo削除部分(自力で) 完成 2 3 4 5
1
環境構築とアプリケーションの立ち上げ
環境構築 - パッケージマネージャー node: JavaScriptで動作するサーバーサイド環境 npm:
いろんな便利パッケージを管理してくれるマネー ジャー (yarn入れるのに使って以降ほとんど使ってない) yarn: npmの上位互換(便利) # nodeの確認(入ってなかったらインストール) $ node -v # npmの確認(入ってなかったらインストール) $ npm -v # yarnの確認 $ yarn -v # yarnがない場合(任意) # npm 経由でyarnをインストール $ npm install -g yarn # yarnのバージョンを確認 $ yarn -v # yarnの初期設定 $ yarn init
環境構築 - create-react-app yarn (global) add, npm install (-g):
パッケージマネージャ(yarnかnpm)を使って、 ライブラリなどのパッケージをインストールする # create-react-appをインストール $ yarn global add create-react-app (または npm install -g create-react-app) 〜 以上! 〜 create-react-app便利! create-react-app: Reactのアプリケーションの設定を色々行ってくれる超 便利ツール
実際にアプリケーションを立ち上げてみる
実際にアプリケーションを立ち上げてみる # まずは、ワークスペースに行く(なければ作る) $ cd workspace # create-react-appで、react-todoという名前のアプリケーションを作成する $ create-react-app
react-todo $ cd react-todo # 始める $ npm start または yarn start mkdir woekspace
実際にアプリケーションを立ち上げてみる 〜 スクリーンで説明 〜
ページ遷移を作ってみよう
ページ遷移を作ってみよう 1. ルーターのライブラリをインストール 2. ルーターの説明と、設定 3. 新規ページ作成と、ページ遷移
ページ遷移を作ってみよう 1. ルーターのライブラリをインストール 2. ルーターの説明と、設定 3. 新規ページ作成と、ページ遷移
react-router-dom: Reactのルーティングをやってくれるライブラリ (ページ遷移や、ページ遷移情報管理など) # react-router-dom をインストール $ yarn
add react-router-dom # package.jsonをみてみる ルーターのライブラリをインストール ライブラリを選ぶときは、 機能で検索してみて「スター数の多いもの」 「ドキュメントや解説記事が豊富なもの」 などを選ぶと良い。 Point
ページ遷移を作ってみよう 1. ルーターのライブラリをインストール 2. ルーターの説明と、設定 3. 新規ページ作成と、ページ遷移
import ~ from ‘xxx’: ‘xxx’のデフォルトでexportされているものを取ってくる import {hoge} from ‘yyy’:
‘yyy’のexportされているもののうち、 hogeっていう名前のものを取ってくる import React from "react"; import { BrowserRouter as Router, Route, Switch } from "react-router-dom"; import App from "./App.js"; ルーターの説明と設定 - 必要なパッケージをimportする Router.jsx src以下にRouter.jsxを作成 (jsでもいいけど、jsxの方がアイコンがかっこいい)
export default x : このファイルをimportされたら、 デフォルトで x を渡す
~ import 系 ~ export default class Root extends React.Component { render() { return ( <Router> <Route exact path="/" component={App} /> </Router> ); } } ルーターの説明と設定 - Routerの中身を作っていく1 Router.jsx class yy extends React.Component : React.Componentを継承した yyクラスを作成 (ここはなんとなくでいいです。) render() : ライフサイクルメソッド(後述) この中身がレンダーされる
Router: 内包したもののルーティングが行える。 (基本1アプリに1つ) ~ import 系 ~ export
default class Root extends React.Component { render() { return ( <Router> <Route exact path="/" component={App} /> </Router> ); } } ルーターの説明と設定 - Routerの中身を作っていく2 Router.jsx Route: 条件とパスが一致している時、そのコンポーネントが renderする exact は、「完全一致したら」という意味で、 pathは、「条件」 exactがあると「localhost:~~~/a」などのパスでは動かな くなる
ReactDOM.render(xx, yy): yyの場所に、xxをレンダーさせる // 読み込むファイルをRouter(.jsx)に変更 import App from './App'; → import
Router from "./Router"; // 上記に伴う変更 ReactDOM.render(<App />, document.getElementById("root")); → ReactDOM.render(<Router />, document.getElementById("root")); ルーターの説明と設定 - Routerを参照させる index.js index.jsに移動 document.getElementById(‘zz’): zzというidの要素を取得
ページ遷移を作ってみよう 1. ルーターのライブラリをインストール 2. ルーターの説明と、設定 3. 新規ページ作成と、ページ遷移
新規ページ作成と、ページ遷移 - 新規ページの中身を作る ToDo.jsxを作成し、App.jsをコピペ import React from 'react' import logo
from './logo.svg' class ToDo extends React.Component { render() { return ( <div className="App"> <header className="App-header"> <img src={logo} className="App-logo" alt="logo" /> <p>ToDo ページだよ</p> </header> </div> ); } } export default ToDo; ToDo.jsx <p>の中身を 「ToDoページ」と書き換え ※右のコードと中身が違うので、 右の通り書き換えてください
Switch: 内包しているコンポーネントのうち、ひとつだけrender する ~ import 系 ~ export default
class Root extends React.Component { render() { return ( <Router> <Switch> <Route exact path="/" component={App} /> </Switch> </Router> ); } } 新規ページ作成と、ページ遷移 - Switchも置いとく Router.jsx
新規ページ作成と、ページ遷移 - Routerに追加する ToDoをimport ToDoのRouteを作る ~ import 系 ~ import
ToDo from "./ToDo"; export default class Root extends React.Component { render() { return ( <Router> <Switch> <Route exact path="/" component={App} /> <Route exact path="/todo" component={ToDo} /> </Switch> </Router> ); } } Router.jsx
新規ページ作成と、ページ遷移 - リンクを作る react-router-domから、Linkをimport <Link to=’/todo’>~</Link>: aタグのような感じ これでページ遷移は完成
~ import 系 ~ import {Link} from "react-router-dom"; export default class App extends React.Component { render() { return ( <div> 〜 略 〜 <Link to="/todo">ToDoページにいく!</Link> </div> ); } } App.jsx
ページ遷移を作ってみよう まとめ 1. ルーターのライブラリをインストール(最初だけ) 2. ルーターの説明と、設定 3. 新規ページ作成と、ページ遷移
・新規ページ作成 → Routerに追加 → リンクを作る
ようやくToDoリストを作っていくっ!
ようやくToDoリストを作っていくっ! 説明 1. ライフサイクルメソッドについて 2. state(とprops)について
ライフサイクルメソッドについて - 全体の流れ Mounting (表示処理) Updating (更新処理) Unmounting (非表示処理) Unmountされる
Update (表示の更新)
ライフサイクルメソッドについて - Mounting Mounting: コンポーネントが描画されるまでの期間。 Mountingで行われるライフサイクルメソッドは Mounting
・constructor():初期化 ・static getDerivedStateFromProps():~ 略 ~ ・render():DOMを表示する ・componentDidMount():renderされた後に発火。
ライフサイクルメソッドについて - Updating Updating: コンポーネントのrender後、Unmountされるまでの期間 propsやstateが変更された際に何度でも呼ばれる Updatingで行われるライフサイクルメソッドは
Updating ・getDerivedStateFromProps():~ 略 ~ ・shouldComponentUpdate():~ 略 ~ ・render():~ 略 ~ ・getSnapshotBeforeUpdate():~ 略 ~ ・componentDidUpdate():~ 略 ~
ライフサイクルメソッドについて - Unmounting Unmounting: コンポーネントが消えるのが決まってから消えるまでの期間 Unmountingで行われるライフサイクルメソッドは Unmounting
・componentWillUnMount():DOMが消える直前に発火
ライフサイクルメソッドについて - 全体の流れ Mounting Updating Unmounting Unmountされる constructor() render() componentDidMount()
などなど render() などなど componentWillUnMou nt() などなど 一度だけ実行 一度だけ実行 何度も実行可 propsやstate の変更
ライフサイクルメソッドについて - 重要なやつ Mounting Updating Unmounting ・constructor() ・render() ・componentDidMount()
・render() ・componentWillUnmount() 覚えるやつ updatingのメソッドは、 パフォーマンスに影響しやすいので、 使うべきときしか使わない! しっかり調べて使うなら◯ Point
console.log(): developer toolに()内のものを表示する ※ここでは、render という文字列と、state(今は空っぽ) を表示させています。 ~
import 系 ~ class ToDo extends Component { render() { console.log( "render") console.log(this.state) return ( <div className="App"> <header className="App-header"> <img src={logo} className="App-logo" alt="logo" /> <p>ToDo ページだよ</p> </header> </div> ); } } ToDo.jsx ライフサイクルメソッドについて - render()編
constructor(props) { super(props); }: クラス内でpropsというものを使う際に必要(後述) this.state = {}:
state(変数など)の宣言と初期化 ~ import 系 ~ class ToDo extends Component { constructor(props) { super(props) console.log( "constructor ") this.state = { // ~ ToDo に必要な変数 ~ } } render() { ~ 略 ~ } } export default ToDo; ToDo.jsx ライフサイクルメソッドについて - constructor()編
const : 定数(再代入不可の変数)の宣言 ToDo.jsx ~ import 系 ~ const
toDoFromDB = [ "Reactハンズオンにいく ", "英語の勉強する ", "ゲームする" ] class ToDo extends Component { constructor(props) { ~ 略 ~ } componentDidMount() { console.log( "componentDidMount ") this.setState({ // ~ state にtodoを入れる処理 ~ }) } render() { ~ 略 ~ } ライフサイクルメソッドについて - componentDidMount()編 外部にあるDBからデータを取ってきたりするの は基本ここ。 (今回はDBがないので、 「toDoFromDB」というのが外部から取ってきた 値だと思ってください ) Point this.setState: stateの更新を行う処理 (stateの変更を行い、 それに伴って再レンダリングされます。)
stateとして、 ToDoリストの配列と、 ToDoの入力用の変数が必要だっ!() ~ import 系 ~ class ToDo extends
Component { constructor(props) { ~ 略 ~ this.state = { toDoList: [], text: "" } } render() ~ 略 ~ } export default ToDo; ToDo.jsx ライフサイクルメソッドについて - stateの宣言 プログラミング学習をする際は、 とりあえずコードを写して、 実行できたあとで「なぜそうなったか」を考える 方が習得が早い!! Point 「、、、ちょっと何言ってるかわからない」 って思っても、「とりあえず、そうなんだぁ」と思ってください 多分これが今日の内容で一番大事です
~ import 系 ~ const toDoFromDB = [ ~ 略
~ ] class ToDo extends Component { constructor() { ~ 略 ~ } componentDidMount() { console.log( "componentDidMount ") this.setState({ toDoList: toDoFromDB }) } render() { ~ 略 ~ } } ToDo.jsx ライフサイクルメソッドについて - stateの変更 this.setState({ [変更するstate名]: [その中身] }) Point
コンソールを見ながら、ライフサイクルを追ってみましょう。 ライフサイクルメソッドについて - 確認
ライフサイクルメソッドについて - 全体の流れ(再掲) Mounting Updating Unmounting Unmountされる constructor() render() componentDidMount()
などなど render() などなど componentWillUnMou nt() などなど 一度だけ実行 一度だけ実行 何度も実行可 propsやstate の変更
~ import 系 ~ class ToDo extends Component { ~
略 ~ render() { ~ 略 ~ return ( <div> <h2>この下にToDoがくるよ</h2> {this.state.toDoList.map((todo, idx) => { return <p key={todo}>{todo}</p>; })} </div> ) } } ToDo.jsx ライフサイクルメソッドについて - stateを反映させる まるっと置き換えました。 (render内の) {}: {}で囲めば、 Javascriptの構文をいれれる 配列.map((val, index) => {}): 配列から一つ一つの値を取りだして、{}内の処理を行 う。 ここでは、toDoListを展開して一つ一つのToDoを pタグで出力してます。 key: render内でmapした場合は、 その中身固有の値をkeyとして持たせないと、 更新がうまくいかなかったりします。
ToDo作成部分を作っていくっ!
ToDo作成部分を作っていくっ! 1. 入力欄と追加ボタンを形だけ作ってみる 2. 入力受付の処理を作る 3. ToDo追加の処理を作る
ToDo作成部分を作っていくっ! 1. 入力欄と追加ボタンを形だけ作ってみる 2. 入力受付の処理を作る 3. ToDo追加の処理を作る
render() { ~ 略 ~ return ( <div> <input />
<button> 追加</button> <h2>この下にToDoがくるよ</h2> {this.state.toDoList.map(todo => { return <p key={todo}>{todo}</p>; })} </div> ) } ToDo.jsx 入力欄と決定ボタンを形だけ作ってみる 簡単
ToDo作成部分を作っていくっ! 1. 入力欄と追加ボタンを形だけ作ってみる 2. 入力受付の処理を作る 3. ToDo追加の処理を作る
入力受付の処理を作る 入力ハンドリング 1. 入力があるたびにonChangeイベントをとる方法 (Controlled Component) 2. なにかしらのアクションがあったらinputのDOM内の値をとる方法 (Uncontrolled
Component) 今回は、1で実装します。 controlled/uncontrolled componentについて、詳しく知りたい人は、検索してみてください。
handleChange = (e) => { console.log(e.target.value) // 入力受付の処理 } render()
{ ~ 略 ~ return ( <div> <input onChange={this.handleChange} /> ~ 略 ~ </div> ) } ToDo.jsx 入力受付の処理を作る - 入力のハンドリング onChange: DOM要素の状態に変更があった場合に呼ばれる プログラミング学習をする際は、 とりあえずコードを写して、 実行できたあとで「なぜそうなったか」を考える 方が習得が早い!! Point 「input要素に変更があるたびにToDoクラス内の handleChangeを実行する」という意味 handleChangeでthis.state.textを更新する
constructor(props) { this.state = { toDoList: [], text: "" }
} handleChange = (e) => { console.log(e.target.value) // ここはどうなるでしょうか? } render() { ~ 略 ~ <input ~ 略 ~ value={this.state.text } ~ 略 ~ } ToDo.jsx 入力受付の処理を作る - stateの宣言と変更 入力中のtoDo用のstateを追加 this.setState({ [変更するstate名]: [その中身] }) Point
ToDo作成部分を作っていくっ! 1. 入力欄と追加ボタンを形だけ作ってみる 2. 入力受付の処理を作る 3. ToDo追加の処理を作る
handleSubmit = () => { // タスク追加の処理 } render() {
~ 略 ~ return ( <div> ~ 略 ~ <button onClick={this.handleSubmit} /> ~ 略 ~ </div> ) } ToDo.jsx ToDo追加の処理を作る onClick: 要素がクリックされたときに呼ばれる 「button要素がクリックされたらToDoクラス内の handleSubmitを実行する」という意味
handleSubmit = () => { this.setState({ toDoList:[...this.state.toDoList, this.state.text], text: ""
}) } render() { ~ 略 ~ return ( <div> ~ 略 ~ <button onClick={this.handleSubmit}> 追加</button> ~ 略 ~ </div> ) ToDo.jsx ToDo追加の処理を作る ...[配列名]: 配列を展開する ここでは、 元のtoDoListの配列を展開 し、 その末尾に新しいstateを追加した配列 を setStateしている (そのあと、入力欄を空に戻してる)
ToDo、消せないとダメ説
まずは、自力でやってみてください
ToDoリストからタスクを削除する - ヒント ヒント 1. 各ToDoの横に削除ボタンを作ろう (エラーが出たら、エラーコードをコピペして検索してみよう) 2. ボタンに削除機能をつけよう
...[配列] or [配列].splice() or [配列].filter(val, index) => {} を使えば配列を展開、setStateできます。
完成!
おしまい
時間が余ったので、 (そして、見た目が良くないので) CSSの当て方
CSSの当て方 色々方法はあるのですが、、、 1. インラインスタイル 2. styled-components という二つを紹介します。
return ( <div style={{ display: "flex", padding: 5 }} >
<button style={{ height: 30 }} > 削除</button> </div> ) インラインスタイル style={{ [プロパティ名]: [値], ... }} (値が、文字列の場合は’’で囲む必要あり)
styled-components: React内でCSSっぽくスタイルを当てれる。 after要素, before要素なども扱える # styled-components $
yarn add styled-components # 使い方 const Wrapper = styled.div` display: flex; padding: 5px; ` const Button = styled.button` height: 30px; ` return ( <Wrapper> <Button>追加</Button> </Wrapper> ) styled-components const AA = styled.タグ名` [プロパティ名]: [値] ` または、 const BB = styled(AA)` [プロパティ名]: [値] `
あとは、自由に 時間があれば、質問など募集してます。