Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Reactハンズオン資料~簡単なToDoアプリ作成~

Avatar for Masa Masa
May 25, 2019

 Reactハンズオン資料~簡単なToDoアプリ作成~

ToDoアプリの実装をしながら、
Reactのライフサイクルメソッドやstateに関する実装を学べるようなハンズオン資料です。

Avatar for Masa

Masa

May 25, 2019
Tweet

Other Decks in Programming

Transcript

  1. 自己紹介
 
 ヤマダマサユキ(24) (@masaofyamad)
 Reactとfirebaseが好き
 元Pear Inc. エンジニア
 元Lyact Inc.

    COO
 現在:ヒモニート(フリーランスエンジニア )
 背景を考えながら
 ホームページ作ったり
 デザインをしたり
 システム作ったりするのが好きです。
 いい写真を
 探したけど
 
 遠いのしか
 なかったです...

  2. はじめに
 環境
 • nodeJSの動作環境
 (npmのインストール)
 知識
 • HTML, CSSが扱える
 •

    (JavaScriptの)変数や配列, イベントハンドリングなどについておおよそ理解してい る
 (理解する気持ちだけでも可)

  3. Reactについて(おおざっぱ)
 • フロントエンド開発用のJavaScriptのライブラリ
 
 • 見えるところは全部できる
 (表示・ページ遷移・アニメーション)
 
 • React

    Native(アプリ用)や、React VR(VR用)などの仲間がいる
 (構文が似ているので、すぐ慣れる)
 そして、HTML, CSSに比べて、とっても早い!
  4. 今回やらないこと 
 • 直接実装に関係のないこと
 
 • 見た目を整えること
 
 • ホスティング


    (サーバーを置いて、どの端末からでもアクセスできるようにすること)
 
 • データベース管理
 
 ほんとに「Reactのみを扱います」

  5. 環境構築 - パッケージマネージャー
 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
  6. 環境構築 - 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のアプリケーションの設定を色々行ってくれる超 便利ツール

  7. react-router-dom:
 Reactのルーティングをやってくれるライブラリ 
 (ページ遷移や、ページ遷移情報管理など) 
 # react-router-dom をインストール $ yarn

    add react-router-dom # package.jsonをみてみる ルーターのライブラリをインストール
 ライブラリを選ぶときは、 
 機能で検索してみて「スター数の多いもの」 
 「ドキュメントや解説記事が豊富なもの」 
 などを選ぶと良い。 Point
  8. 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の方がアイコンがかっこいい)
  9. 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() : 
 ライフサイクルメソッド(後述) 
 この中身がレンダーされる
  10. 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」などのパスでは動かな くなる

  11. 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の要素を取得 
 

  12. 新規ページ作成と、ページ遷移 - 新規ページの中身を作る
 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ページ」と書き換え
 ※右のコードと中身が違うので、 
 右の通り書き換えてください 

  13. Switch:
 内包しているコンポーネントのうち、ひとつだけrender する
 
 ~ import 系 ~ export default

    class Root extends React.Component { render() { return ( <Router>    <Switch> <Route exact path="/" component={App} /> </Switch> </Router> ); } } 新規ページ作成と、ページ遷移 - Switchも置いとく
 Router.jsx
  14. 新規ページ作成と、ページ遷移 - 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
  15. 新規ページ作成と、ページ遷移 - リンクを作る
 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
  16. ライフサイクルメソッドについて - Mounting
 Mounting:
 コンポーネントが描画されるまでの期間。 
 
 Mountingで行われるライフサイクルメソッドは 
 Mounting

    ・constructor():初期化 
 ・static getDerivedStateFromProps():~ 略 ~ 
 ・render():DOMを表示する 
 ・componentDidMount():renderされた後に発火。
  17. ライフサイクルメソッドについて - Updating
 Updating:
 コンポーネントのrender後、Unmountされるまでの期間 
 propsやstateが変更された際に何度でも呼ばれる 
 
 Updatingで行われるライフサイクルメソッドは

    
 Updating ・getDerivedStateFromProps():~ 略 ~ 
 ・shouldComponentUpdate():~ 略 ~ 
 ・render():~ 略 ~
 ・getSnapshotBeforeUpdate():~ 略 ~ 
 ・componentDidUpdate():~ 略 ~ 

  18. ライフサイクルメソッドについて - 全体の流れ
 Mounting Updating Unmounting Unmountされる constructor() render() componentDidMount()

    などなど render() などなど componentWillUnMou nt() などなど 一度だけ実行 一度だけ実行 何度も実行可 propsやstate の変更
  19. ライフサイクルメソッドについて - 重要なやつ
 Mounting Updating Unmounting ・constructor()
 ・render()
 ・componentDidMount() 


    ・render()
 
 ・componentWillUnmount() 
 覚えるやつ updatingのメソッドは、 パフォーマンスに影響しやすいので、 使うべきときしか使わない! しっかり調べて使うなら◯ Point
  20. 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()編

  21. 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()編

  22. 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の変更を行い、 
 それに伴って再レンダリングされます。) 

  23. stateとして、
 ToDoリストの配列と、
 ToDoの入力用の変数が必要だっ!()
 ~ import 系 ~ class ToDo extends

    Component { constructor(props) {   ~ 略 ~  this.state = { toDoList: [], text: "" } } render() ~ 略 ~ } export default ToDo; ToDo.jsx ライフサイクルメソッドについて - stateの宣言
 プログラミング学習をする際は、 とりあえずコードを写して、 実行できたあとで「なぜそうなったか」を考える 方が習得が早い!! Point 「、、、ちょっと何言ってるかわからない」 
 って思っても、「とりあえず、そうなんだぁ」と思ってください 
 多分これが今日の内容で一番大事です
  24. ~ import 系 ~ const toDoFromDB = [ ~ 略

    ~ ] class ToDo extends Component { constructor() { ~ 略 ~ } componentDidMount() { console.log( "componentDidMount ") this.setState({ toDoList: toDoFromDB }) } render() { ~ 略 ~ } } ToDo.jsx ライフサイクルメソッドについて - stateの変更
 this.setState({ [変更するstate名]: [その中身] }) Point
  25. ライフサイクルメソッドについて - 全体の流れ(再掲)
 Mounting Updating Unmounting Unmountされる constructor() render() componentDidMount()

    などなど render() などなど componentWillUnMou nt() などなど 一度だけ実行 一度だけ実行 何度も実行可 propsやstate の変更
  26. ~ 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として持たせないと、 
 更新がうまくいかなかったりします。 

  27. render() { ~ 略 ~ return ( <div> <input />

    <button> 追加</button> <h2>この下にToDoがくるよ</h2> {this.state.toDoList.map(todo => { return <p key={todo}>{todo}</p>; })} </div> ) } ToDo.jsx 入力欄と決定ボタンを形だけ作ってみる
 簡単

  28. 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を更新する 

  29. 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
  30. handleSubmit = () => { // タスク追加の処理 } render() {

    ~ 略 ~ return ( <div> ~ 略 ~ <button onClick={this.handleSubmit} />   ~ 略 ~ </div> ) } ToDo.jsx ToDo追加の処理を作る
 onClick:
 要素がクリックされたときに呼ばれる 
 
 「button要素がクリックされたらToDoクラス内の handleSubmitを実行する」という意味 
 
 

  31. 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している
 (そのあと、入力欄を空に戻してる) 

  32. return ( <div style={{ display: "flex", padding: 5 }} >

    <button style={{ height: 30 }} > 削除</button> </div> ) インラインスタイル
 style={{ 
 [プロパティ名]: [値], 
 ...
 }}
 (値が、文字列の場合は’’で囲む必要あり) 

  33. 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)` 
 [プロパティ名]: [値] 
 `