- 投稿日:2019-03-05T23:51:32+09:00
[備忘録]Reactについての個人メモ
React勉強の備忘録
Reactとは
javascriptのライブラリ
DOMの更新とイベントハンドリングをやってくれるライブラリ
MVCのviewの役割だけ
ReactではDOMの更新に仮想DOMを使っている
Reactではコンポーネントという単位でUIパーツを作るメリット
早い
Reactの書き方がコンポーネント単位だから再利用しやすく保守性が高いDOMとは
Document Object Model
DOMは文書をノードとオブジェクトで表現し、その文書を表現、保存、操作する方法らしい。JSX
htmlみたいに書かれているけれど、Babelでコンパイルして使う
Reactのために作られたjavascriptの書き方Reactを触っていて直感的に理解しにくかったところ
- PropTypes
- State
- 仮想DOM これはまた近いうちに勉強しよう。。
これからまとめたいと思っているところ
- Reactの基本的な構造?図解したいなー
- Reactのデプロイ方法一個
- DOMについて
感想
ざっくり自分用のメモをまとめてみた感じになってしまっていろんなサイトのURLを貼ってしまったけどいいのかなこれ。。
とりあえず、最初から作ってみるのは個人的に気持ち悪かったのであさーく特徴とかさらっとこうかなくらいのメモでした。
次の記事は実際にコード書きながら理解したことを記録していきたいなと
- 投稿日:2019-03-05T20:39:28+09:00
Sass map eachを使って色を指定する
以外と知らない人が多そうなので出力します。
各要素に応じて色を定義している場合があると思います。
例えば信号の状態を表現する以下のようなcssがあります。.signal-stop { color: #dd0000; } .signal-caution { color: #f4e542; } .signal-go { color: #5ce053; }これをmapを使うと以下のように記述することができます。
$map: (stop: #dd0000, caution: #f4e542, go: #5ce053); @each $state, $color in $map { signal-#{$state} { color: $color; } }例えば、これに信号が停電するような場合を追加する場合は
$map: (stop: #dd0000, caution: #f4e542, go: #5ce053, blackout: #000000 );とすれば済みそうです。実際のコードでは状態が8つあったので大分スッキリさせることができました。
https://sass-lang.com/documentation/file.SASS_REFERENCE.html#each-multi-assign
https://sass-lang.com/documentation/file.SASS_REFERENCE.html#lists
https://www.sassmeister.com/
- 投稿日:2019-03-05T15:20:34+09:00
【React】超ざっくり入門(Hooks)
概要
React16.8から新しい機能として
Hooks
が導入されました。
以下の順序でHooks
とは何かざっくり入門していきましょう。Hooksとは?
Hooks
とは従来classコンポーネントでしか使用できなかったstate
等の機能をfunctionalコンポーネント(関数コンポーネント)でも使用可能にする機能です。この記事では以下の3種類の
hook
を紹介します。
- (1)State Hook:
state
やsetState
を関数コンポーネント内で使用可能にする。- (2)Effect Hook:データ取得やDOM変更といった
side effects
を関数コンポーネント内で使用可能にする。- (3)Custom Hooks:共通のロジックをコンポーネント間での再利用を可能にする。
Hooksの規則
Hooks
を使用する際には以下の規則を守りましょう。
- (1) Hooksは必ずコンポーネント中の一番上(
トップレベル
)に定義する。(ループ、条件分岐、ネストされた関数の中で定義してはいけません。)- (2) HooksはReactの関数コンポーネントの中だけで呼ぶ。(通常のJavascriptの関数から使用してはいけません。)
State Hook
上記で記した様に、
state
やsetState
を関数コンポーネント内で行える様にします。
具体的にはuseState
と呼ばれるhookを使用します。
useState
の使用方法を従来のclassコンポーネント
と比較して確認していきます。従来のclassコンポーネント
以下の例では主に2つの事を行なっています。
- (1)
state
で初期値に0
を持つcount
を定義する。- (2)
setState
でボタンを押すたびにcount
に1
を足している。class Example extends React.Component { constructor(props) { super(props); this.state = { count: 0 }; } render() { return ( <div> <p>{this.state.count} 回クリックしました。</p> <button onClick={() => this.setState({ count: this.state.count + 1 })}> クリックしてください。 </button> </div> ); } }StateHook
上記と全く同じ事を
useState
を使用して行います。まず
useState
をインポートしましょう。import React, { useState } from 'react';
useState
では従来のstate
とsetState
を同時に設定します。
以下の3点に注目して以下のコードを見てみましょう。
- (1)
count
がclassコンポーネントでいうthis.state={count:0}
の部分。- (2)
setCount
がclassコンポーネントでいうsetState
の部分。- (3)
useState()
に渡されている0
がcount
の初期値。import React, { useState } from 'react'; function Counter() { const [count, setCount] = useState(0) }また以下の2点を踏まえて残りのコードを完成させます。
- (1)
state
を直接参照できる。- (2)
setCount
を使用してstate
を更新できる。import React, { useState } from 'react'; function Counter() { const [count, setCount] = useState(0) return( <div> // (1) stateを直接参照できる。 <p>{count} 回クリックしました</p> // (2) setCountを使用してstateを更新できる。 <button onClick={() => setCount(count + 1)}> クリックしてください。</button> </div> ) } export default Counter;ちなみに以下の様にして複数の
state
を定義していきます。import React, { useState } from 'react'; function Counter() { const [count, setCount] = useState(0) const [name, setName] = useState('') return( <div> <p>{count} 回クリックしました</p> <button onClick={() => setCount(count + 1)}> クリックしてください。</button> <p>私の名前は{name}</p> <button onClick={() => setName('テスト太郎')}>名前表示</button> </div> ) } export default Counter;Effect Hook
上記で記した通り、データ取得やDOM変更といった
side effects
を関数コンポーネント内で使用可能にします。従来のclassコンポーネントでは
componentDidMount
やcomponentDidUpdate
、componentWillUnmount
等の中でデータ取得やDOM変更を行なっていましたが、これをuseEffect
と呼ばれるhookを使用し、関数コンポーネントでも使用可能にします。こちらも
useEffect
の使用方法を従来のclassコンポーネント
と比較して確認していきます。従来のclassコンポーネント
従来は
componentDidMount
はマウントされた直後に1回だけ呼ばれ、componentDidUpdate
はコンポーネントが更新された後に呼ばれ、ここでデータの取得等を行いました。import React from 'react'; class Effect extends React.Component { constructor(props) { super(props); this.state = { count: 0 }; } componentDidMount() { console.log('マウントされました。') } componentDidUpdate() { console.log('アップデートされました。') } render() { return ( <div> <h1>{this.state.count} 回クリックしました。</h1> <button onClick={() => this.setState({ count: this.state.count + 1 })}> クリックしてください。 </button> </div> ); } }EffectHook
useEffect
は従来のcomponentDidMount
、componentDidUpdate
、componentWillUnmount
の3つを組み合わせた様なもので、基本的にrenderされる毎に呼ばれます。(first render
を含む。)
hooks
を使用した開発ではここでside effects
を実行します。import React, { useState, useEffect } from 'react' function Effect() { const [count, setCount] = useState(0) useEffect(() => { console.log('レンダーされました。') }) return( <div> <h1>{count} 回クリックしました</h1> <button onClick={() => setCount(count + 1)}> クリックしてください。</button> </div> ); }Custom Hooks
上記で記載した通り、共通のロジックをコンポーネント間での再利用を可能にします。
以下の2つのコンポーネントがあるとします。
- (1) 受け取った
id
が1
だったらログイン中です
を返す、status.js
、- (2) 受け取った
id
が1
だったらおかえりなさい
を返すmessage.js
。status.jsexport default function Status(props){ const [isLoggedIn, setIsLoggedIn] = useState(false); const handleStateChange = (id) => { if(id === 1){ setIsLoggedIn(true) } else{ setIsLoggedIn(false) } } useEffect(() => { handleStateChange(props.user.id) }) const status = isLoggedIn ? 'ログイン中' : 'サインアップ' return ( <> <h1>Status: {status}</h1> </> ) }message.jsexport default function Message(props){ const [isLoggedIn, setIsLoggedIn] = useState(false); const handleStateChange = (id) => { if(id === 1){ setIsLoggedIn(true) } else{ setIsLoggedIn(false) } } useEffect(() => { handleStateChange(props.user.id) }) const message = isLoggedIn ? 'おかえりなさい' : 'おかえりなさい' return ( <> <h1>Message: {message}</h1> </> ) }ここの共通したロジック部分を
custom Hook
を使用する事で、以下の様に抜き出す事ができます。
※抜き出したロジックのコンポーネントはuse
から始まる慣習があります。今回はuseLogin
と名付けました。useLoginimport { useState, useEffect } from 'react'; export default function useLogin(userId){ const [isLoggedIn, setIsLoggedIn] = useState(false); // コンポーネント間で再利用したいロジック const handleStateChange = (id) => { if(id === 1){ setIsLoggedIn(true) } else{ setIsLoggedIn(false) } } // side effectsを実行する。 useEffect(() => { handleStateChange(userId) }) return isLoggedIn; }
useLogin
を使用する事でstatus.js
とmessage.js
をよりスッキリ書くことができます。user.jsimport React from 'react'; import useLogin from './useLogin'; export default function Status(props){ const status = useLogin(props.user.id) ? 'ログイン中' : 'サインアップ' return ( <> <h1>Status: {status}</h1> </> ) }message.jsimport React from 'react'; import useLogin from './useLogin'; export default function Message(props){ const message = useLogin(props.user.id) ? 'おかえりなさい' : 'サインアップしてください' return ( <> <h1>Message: {message}</h1> </> ) }
custom hooks
では他にも色々な事ができるので、詳細は公式ドキュメントで確認ください。参照
hooks
の説明としては本当にざっくりでしたので、詳細は公式ドキュメントで確認ください。
- 投稿日:2019-03-05T15:20:34+09:00
【React】ざっくり入門(Hooks)
概要
React16.8から新しい機能として
Hooks
が導入されました。
以下の順序でHooks
とは何かざっくり入門していきましょう。Hooksとは?
Hooks
とは従来classコンポーネントでしか使用できなかったstate
等の機能をfunctionalコンポーネント(関数コンポーネント)でも使用可能にする機能です。この記事では以下の3種類の
hook
を紹介します。
- (1)State Hook:
state
やsetState
を関数コンポーネント内で使用可能にする。- (2)Effect Hook:データ取得やDOM変更といった
side effects
を関数コンポーネント内で使用可能にする。- (3)Custom Hooks:共通のロジックをコンポーネント間での再利用を可能にする。
Hooksの規則
Hooks
を使用する際には以下の規則を守りましょう。
- (1) Hooksは必ずコンポーネント中の一番上(
トップレベル
)に定義する。- ループ、条件分岐、ネストされた関数の中で定義してはいけません。)
- (2) HooksはReactの関数コンポーネントの中だけで呼ぶ。(通常のJavascriptの関数から使用してはいけません。)
State Hook
useState
と呼ばれるhookを使用する事でstate
やsetState
を関数コンポーネント内で行える様にします。
classコンポーネント
とuseState
を使用した関数コンポーネント
を比較して使用方法を確認して見ましょう。従来のclassコンポーネント
以下の例では主に2つの事を行なっています。
- (1)
state
で初期値に0
を持つcount
を定義する。- (2)
setState
でボタンを押すたびにcount
に1
を足している。class Example extends React.Component { constructor(props) { super(props); this.state = { count: 0 }; } render() { return ( <div> <p>{this.state.count} 回クリックしました。</p> <button onClick={() => this.setState({ count: this.state.count + 1 })}> クリックしてください。 </button> </div> ); } }StateHook
上記と全く同じ事を
useState
を使用して行います。
基本的な使用方法(定義方法)は以下の通りです。const [state, setState] = useState(initialState);
useState
では従来のstate
とsetState
を同時に設定しする様なイメージです。
上記のcount
やそのsetState
をuseState
を使用して定義すると以下の様になります。import React, { useState } from 'react'; function Counter() { const [count, setCount] = useState(0) }以下の3点に注目して上のコードを見てみましょう。
- (1)
count
がclassコンポーネントでいうthis.state={count:0}
の部分。- (2)
setCount
がclassコンポーネントでいうsetState
の部分。- (3)
useState()
に渡されている0
がcount
の初期値。また以下の2点を踏まえて残りのコードを完成させます。
- (1)
state
を直接参照できる。- (2)
setCount
を使用してstate
を更新できる。import React, { useState } from 'react'; function Counter() { const [count, setCount] = useState(0) return( <div> // (1) stateを直接参照できる。 <p>{count} 回クリックしました</p> // (2) setCountを使用してstateを更新できる。 <button onClick={() => setCount(count + 1)}> クリックしてください。</button> </div> ) } export default Counter;ちなみに以下の様にして複数の
state
を定義していきます。import React, { useState } from 'react'; function Counter() { const [count, setCount] = useState(0) const [name, setName] = useState('') return( <div> <p>{count} 回クリックしました</p> <button onClick={() => setCount(count + 1)}> クリックしてください。</button> <p>私の名前は{name}</p> <button onClick={() => setName('テスト太郎')}>名前表示</button> </div> ) } export default Counter;Effect Hook
従来のclassコンポーネントでは
componentDidMount
やcomponentDidUpdate
、componentWillUnmount
等の中でデータ取得やDOM変更を行なっていましたが、これをuseEffect
と呼ばれるhookを使用し、関数コンポーネントでも使用可能にします。こちらも
useEffect
の使用方法を従来のclassコンポーネント
と比較して確認していきます。従来のclassコンポーネント
従来は
componentDidMount
はマウントされた直後に1回だけ呼ばれ、componentDidUpdate
はコンポーネントが更新された後に呼ばれ、ここでデータの取得等を行いました。import React from 'react'; class Effect extends React.Component { constructor(props) { super(props); this.state = { count: 0 }; } componentDidMount() { console.log('マウントされました。') } componentDidUpdate() { console.log('アップデートされました。') } render() { return ( <div> <h1>{this.state.count} 回クリックしました。</h1> <button onClick={() => this.setState({ count: this.state.count + 1 })}> クリックしてください。 </button> </div> ); } }EffectHook
useEffect
は従来のcomponentDidMount
、componentDidUpdate
、componentWillUnmount
の3つを組み合わせた様なもので、基本的にrenderされる毎に呼ばれます。(first render
を含む。)
hooks
を使用した開発ではここでside effects
を実行します。import React, { useState, useEffect } from 'react' function Effect() { const [count, setCount] = useState(0) useEffect(() => { console.log('レンダーされました。') }) return( <div> <h1>{count} 回クリックしました</h1> <button onClick={() => setCount(count + 1)}> クリックしてください。</button> </div> ); }Custom Hooks
上記で記載した通り、共通のロジックをコンポーネント間での再利用を可能にします。
以下の2つのコンポーネントがあるとします。
- (1) 受け取った
id
が1
だったらログイン中です
を返す、status.js
、- (2) 受け取った
id
が1
だったらおかえりなさい
を返すmessage.js
。status.jsexport default function Status(props){ const [isLoggedIn, setIsLoggedIn] = useState(false); const handleStateChange = (id) => { if(id === 1){ setIsLoggedIn(true) } else{ setIsLoggedIn(false) } } useEffect(() => { handleStateChange(props.user.id) }) const status = isLoggedIn ? 'ログイン中' : 'サインアップ' return ( <> <h1>Status: {status}</h1> </> ) }message.jsexport default function Message(props){ const [isLoggedIn, setIsLoggedIn] = useState(false); const handleStateChange = (id) => { if(id === 1){ setIsLoggedIn(true) } else{ setIsLoggedIn(false) } } useEffect(() => { handleStateChange(props.user.id) }) const message = isLoggedIn ? 'おかえりなさい' : 'あなたは誰ですか?' return ( <> <h1>Message: {message}</h1> </> ) }ここの共通したロジック部分を
custom Hook
を使用する事で、以下の様に抜き出す事ができます。
※抜き出したロジックのコンポーネントはuse
から始まる慣習があります。今回はuseLogin
と名付けました。useLoginimport { useState, useEffect } from 'react'; export default function useLogin(userId){ const [isLoggedIn, setIsLoggedIn] = useState(false); // コンポーネント間で再利用したいロジック const handleStateChange = (id) => { if(id === 1){ setIsLoggedIn(true) } else{ setIsLoggedIn(false) } } // side effectsを実行する。 useEffect(() => { handleStateChange(userId) }) return isLoggedIn; }
useLogin
を使用する事でstatus.js
とmessage.js
をよりスッキリ書くことができます。user.jsimport React from 'react'; import useLogin from './useLogin'; export default function Status(props){ const status = useLogin(props.user.id) ? 'ログイン中' : 'サインアップ' return ( <> <h1>Status: {status}</h1> </> ) }message.jsimport React from 'react'; import useLogin from './useLogin'; export default function Message(props){ const message = useLogin(props.user.id) ? 'おかえりなさい' : 'サインアップしてください' return ( <> <h1>Message: {message}</h1> </> ) }
custom hooks
では他にも色々な事ができるので、詳細は公式ドキュメントで確認ください。参照
hooks
の説明としては本当にざっくりでしたので、詳細は公式ドキュメントで確認ください。
- 投稿日:2019-03-05T12:17:34+09:00
Jestのスナップショットテストを導入してみる
?初心者です。
社内で運用しているアプリケーションがReact.jsを使っているので、Jestが用意しているスナップショットテストを導入することにしました!
【導入のきっかけ】
現在進行形で既にあるアプリケーションのバグを対応することになりました。
ブラウザバックすると予期せぬコンポーネントでエラーになってしまい、結果画面真っ白になってしまうとか…
共通のヘッダーコンポーネントを修正しなければならなそうで、もし1行変えただけで全体に影響を及ぼしてしまったら…? スナップショットが入っていれば、1行対応した後にテストコマンド一つでスナップショットの差分が分かり、どこが変わったか一発で分かります!
スナップショットもGitで管理すると良いです☺️【まずは下準備】
必要なライブラリをインストールしておきます。
$ yarn add -D babel-jest enzyme enzyme-adapter-react-16 react-test-rendererimportしているコンポーネントのパスがエイリアスになっているので、そこも解消するべくpackage.jsonに追記します。今回はエイリアス
@app/***/***
用に下のような記述をしています。{ ... "jest": { "moduleNameMapper": { "^@app(.*)$": "<rootDir>/src/app$1" }, "verbose": true, "setupFiles": [ "<rootDir>/setupTests.js" ], "moduleFileExtensions": [ "js", "json", "jsx" ] } ... }↑ 参考:Solve Module Import Aliasing for Webpack, Jest, and VSCode
setupTests.js
の内容はこちらです!
enzymeの指定をしており、packge.jsonのsetupFiles
で読み込ませています。import Enzyme from 'enzyme' import EnzymeAdapter from 'enzyme-adapter-react-16' Enzyme.configure({ adapter: new EnzymeAdapter(), disableLifecycleMethods: true, })【いざ、実践!】
やり方は公式サイトを参考に始めます。
今回実装するきっかけになったヘッダーコンポーネントから実装してみます!
公式サイトを見る限り簡単そう。?
余裕でしょ!笑一番最初に書いた記述がこちら!
■失敗その1
import React from 'react' import renderer from 'react-test-renderer' import { CommonHeader } from 'Components/Common/Header' describe('<CommonHeader />', () => { it('スナップショット', () => { const tree = renderer .create(<CommonHeader />) .toJSON() expect(tree).toMatchSnapshot() }) })これでは上手くいかず、こんなエラーが表示されました。
TypeError: this.props.handleFetchUser is not a function
コンポーネントでは、
handleFetchUser
をmapDispatchToProps
で呼び出しています。
propsを渡せていないことによるエラーが他に1つ出ていたので、こちらを解消します!■失敗その2
describe('<CommonHeader />', () => { it('スナップショット', () => { const props = { match: {}, handleFetchUser: jest.fn() } const tree = renderer.create(<CommonHeader {...props} />).toJSON() expect(tree).toMatchSnapshot() }) })エラーになっていたpropsを最初に指定してあげ、
<CommonHeader />
に渡してあげています。ですが、今度はこんなエラーが出てしまいました!
Warning: Failed context type: The context `router` is marked as required in `Link`, but its value is `undefined`.Invariant Violation: You should not use <Link> outside a <Router>というわけで
<CommonHeader />
を<Router />
で囲ってあげましょう!■ 完成形
import { BrowserRouter as Router } from 'react-router-dom' describe('<CommonHeader />', () => { it('スナップショット', () => { const props = { match: {}, handleFetchUser: jest.fn() } const tree = renderer .create( <Router> <CommonHeader {...props} /> </Router> ) .toJSON() expect(tree).toMatchSnapshot() }) })成功だ!と思ったら、
console.warn
の文字が…
全部緑色の方が清々しいので、このエラーについてググってみました。
対応策の中でこれかな…と思うものがあったのですが、今回は目をつぶり、保留とさせていただきます。?↓ 見当違いだったらごめんなさい。
babel-jest does not transpile import/export in node_modules when Babel 7 is used #6229■ react-routerでpathの判定をしていた時
上記はpropsで渡していますが、stach overflowを見ていたら、下のような記述でも行けるようです。
const matchURL = { params: {}, isExact: true, path: "", url: "" } <CommonHeader match={matchURL} />余談
実はこのエラーの前に一つ、ヘッダーの中で非同期通信させています。
そこでenvファイルで管理している値を、process.env
のように使っており、
最初は「process.env.DUMMY_NAMEがありません」と怒られました。
「なんじゃこりゃ!」と思いましたが、このプロジェクトの場合のみpackage.jsonでローカルと同じenvファイルを呼び出したらいけました?テストにパスしたので正常に「
__snapshots__/index.test.js.snap
」ファイルが生成されてくれました…っ!余談パート2
enzymeの
shallow
みたいな書き方もできることを知りました!
公式サイトを見ると、
react-test-rendererには、ShallowRenderer
というのがに用意されているようです。(使ってみたら、上の記述とは違うsnapshotが吐き出されたので、今回は使用しませんでした。)■ さらにさらに
「コンポーネントにsetStateさせた状態でスナップショット撮りたいなぁ…」を叶えてくれるライブラリが紹介されていたので、こちらを採用しました!
「enzyme-to-json」を使用しています。
enzymeのshallow
を使って色々操作した後、toJson
でwrapperを囲ってスナップショットをしてあげれば出来上がりです!expect(toJson(wrapper)).toMatchSnapshot();試しに、setStateでタイトルを指定して、スナップショットの結果が正しく変わってくれるか検証してみました。
import React from 'react' import { shallow } from 'enzyme' import renderer from 'react-test-renderer' import toJson from 'enzyme-to-json' import { CommonHeader } from 'Components/Common/Header' const initialProps = { ... } const setup = (state = {}, props = initialProps) => { const wrapper = shallow(<CommonHeader {...props} />) return wrapper } describe('<CommonHeader />', () => { it('プロジェクト名がH1に表示される', () => { const wrapper = setup() wrapper.setState({ projectName: 'ダミープロジェクト' }) expect(wrapper.find('h1').text()).toEqual('ダミープロジェクト') // PASS expect(toJson(wrapper)).toMatchSnapshot() }) })
enzyme-to-json
の参考になったサイトはこちらです。
・6. Testing react components using Jest and Enzymeスナップショットの結果もsetStateする前後でちゃんと変わってくれました!
【参考にしたサイト】
・What and How to Test with Jest and Enzyme. Full Instruction on React Components Testing
補足
スナップショットの記述を変えてテストを実行していくと、「上書きされた」とエラーが表示されます。
今はゴリゴリテストを実装していくフェーズなので、testの後に-u
をつけて実行しましょう!$ yarn test -u上書きされてテストがパスされていることが確認できます。
【終えて】
参考にしたのはやはりYoutubeとUdemyです!(動画わかりやすくて感覚派の私には最高!笑)
さらに理解を深めたいので、他コンポーネントでもスナップショットテストを書いていきます。
- 投稿日:2019-03-05T09:30:05+09:00
【React】超ざっくり入門(Hooks)
概要
React16.8から新しい機能として
Hooks
が導入されました。
以下の順序でHooks
とは何かざっくり入門していきましょう。Hooksとは?
Hooks
とは従来classコンポーネント
でしか使用できなかったstate
等の機能をfunctionalコンポーネント
でも使用可能にするReactに導入された新しい機能です。この記事では以下の2種類の
hook
を紹介します。
- (1)
State Hook
:state
やsetState
をfunctionalコンポーネント内で使用可能にする。- (2)
Effect Hook
:データ取得やDOM変更といったside effects
をfunctionalコンポーネント内で使用可能にする。Hooksの規則
Hooks
を使用する際には以下の規則を守りましょう。
- (1) Hooksは必ずfunctionalコンポーネント中の一番上(
トップレベル
)に定義する。(ループ、条件分岐、ネストされた関数の中で定義してはいけません。)- (2) HooksはReactのfunctionalコンポーネントの中だけで呼ぶ。(通常のJavascriptの関数から使用してはいけません。)
State Hook
上記で記した様に、
state
やsetState
をfunctionalコンポーネント内で行える様にします。
具体的にはuseState
と呼ばれるhookを使用します。
useState
の使用方法を従来のclassコンポーネント
と比較して確認していきます。従来のclassコンポーネント
以下の例では主に2つの事を行なっています。
- (1)
state
で初期値に0
を持つcount
を定義する。- (2)
setState
でボタンを押すたびにcount
に1
を足している。class Example extends React.Component { constructor(props) { super(props); this.state = { count: 0 }; } render() { return ( <div> <p>{this.state.count} 回クリックしました。</p> <button onClick={() => this.setState({ count: this.state.count + 1 })}> クリックしてください。 </button> </div> ); } }StateHook
上記と全く同じ事を
useState
を使用して行います。まず
useState
をインポートしましょう。import React, { useState } from 'react';
useState
では従来のstate
(ここではcount
)とsetState
を同時に定義します。
以下の2点に注目して以下のコードを見てみましょう。
- (1) 以下の
setCount
がclassコンポーネントでいうsetState
の部分。- (2)
useState()
に渡されている0
がcount
の初期値。import React, { useState } from 'react'; function Counter() { const [count, setCount] = useState(0) }また以下の2点を踏まえて残りのコードを完成させます。
- (1)
state
を直接参照できる。- (2)
setCount
を使用してstate
を更新できる。import React, { useState } from 'react'; function Counter() { const [count, setCount] = useState(0) return( <div> // (1) stateを直接参照できる。 <p>{count} 回クリックしました</p> // (2) setCountを使用してstateを更新できる。 <button onClick={() => setCount(count + 1)}> クリックしてください。</button> </div> ) } export default Counter;ちなみに以下の様にして複数の
state
を定義していきます。import React, { useState } from 'react'; function Counter() { const [count, setCount] = useState(0) const [name, setName] = useState('') return( <div> <p>{count} 回クリックしました</p> <button onClick={() => setCount(count + 1)}> クリックしてください。</button> <p>私の名前は{name}</p> <button onClick={() => setName('テスト太郎')}>名前表示</button> </div> ) } export default Counter;Effect Hook
上記で記した通り、データ取得やDOM変更といった
side effects
をfunctionalfunctionコンポーネント内で使用可能にします。従来のclassコンポーネントでは
componentDidMount
やcomponentDidUpdate
、componentWillUnmount
等の中でデータ取得やDOM変更を行なっていましたが、これをuseEffect
と呼ばれるhookを使用し、functionalコンポーネントでも使用可能にします。こちらも
useEffect
の使用方法を従来のclassコンポーネント
と比較して確認していきます。従来のclassコンポーネント
従来は
componentDidMount
はマウントされた直後に1回だけ呼ばれ、componentDidUpdate
はコンポーネントが更新された後に呼ばれ、ここでデータの取得等を行いました。import React from 'react'; class Effect extends React.Component { constructor(props) { super(props); this.state = { count: 0 }; } componentDidMount() { console.log('マウントされました。') } componentDidUpdate() { console.log('アップデートされました。') } render() { return ( <div> <h1>{this.state.count} 回クリックしました。</h1> <button onClick={() => this.setState({ count: this.state.count + 1 })}> クリックしてください。 </button> </div> ); } }EffectHook
useEffect
は従来のcomponentDidMount
、componentDidUpdate
、componentWillUnmount
の3つを組み合わせた様なもので、基本的にrenderされる毎に呼ばれます。(first render
を含む。)
hooks
を使用した開発ではここでside effects
を実行します。import React, { useState, useEffect } from 'react' function Effect() { const [count, setCount] = useState(0) useEffect(() => { console.log('レンダーされました。') }) return( <div> <h1>{count} 回クリックしました</h1> <button onClick={() => setCount(count + 1)}> クリックしてください。</button> </div> ); }参照
hooks
の説明としては本当にざっくりでしたので、詳細は公式ドキュメントで確認ください。
- 投稿日:2019-03-05T00:50:12+09:00
はじめてのcreate-react-app
最終目標
フロントエンドとバックエンドのDB排他を調べてみたい。
今回の目標
Using React in Visual Studio Code の内容を実施する。
https://code.visualstudio.com/docs/nodejs/reactjs-tutorialOS環境
$ lsb_release -a No LSB modules are available. Distributor ID: Ubuntu Description: Ubuntu 18.04.2 LTS Release: 18.04 Codename: bionic開発環境構築
$ sudo apt update $ sudo apt upgrade -y $ sudo reboot $ sudo apt install nodejs $ node -v v8.10.0 $ sudo apt install npm $ npm -v 3.5.2React環境構築
$ sudo npm install -g create-react-app $ create-react-app --version 2.1.5Reactアプリ作成
$ create-react-app my-app $ cd my-app/ $ npm start外部アクセスのためポートを開放する場合(必要に応じて)
$ sudo ufw allow ssh $ sudo ufw allow 3000Hello World!
src/index.jsimport React from 'react'; import ReactDOM from 'react-dom'; import './index.css'; import App from './App'; import * as serviceWorker from './serviceWorker'; -ReactDOM.render(<App />, document.getElementById('root')); +var element = React.createElement('h1', { className: 'greeting' }, 'Hello, world!'); +ReactDOM.render(element, document.getElementById('root')); // If you want your app to work offline and load faster, you can change // unregister() to register() below. Note this comes with some pitfalls. // Learn more about service workers: http://bit.ly/CRA-PWA serviceWorker.unregister();感想
- モダンな開発スタイルのような気がする
- 次は、MERN Starterを調べてみたい
- AngularとVueも調べてみたい
- TypeScriptも調べてみたい
以上