コネヒト開発者ブログ

コネヒト開発者ブログ

imgix導入でコンテンツダウンロード量を85%削減した話

こんにちは。インフラエンジニアの永井(@shnagai)です。

今回は、imgixという画像変換に対応したCDNを導入して、コンテンツダウンロードの削減を実現した話について書こうと思います。

imgixとは

はじめに、imgixって何と思われる方も多いかと思いますので簡単に特徴を紹介します。

  • クエリパラメータで、画像のリサイズや圧縮が出来るCDNサービス
  • S3をバックエンドに指定出来るので、画像のコピー等が不要でそのまま使える
  • バックエンドはFastlyが使われているので高速配信
  • 国内だと、日経や一休で採用実績あり
  • コストは、標準プランだとCDN Bandwidth: 8¢/GB + Master images accessed $3/1000

imgix • Real-time image processing and image CDN

導入した背景

ママリが運営しているメディアサイトや記事関連のwebviewにおいて、PCサイズの大きめ画像をどのデバイスにおいても配信していたため、コンテンツダウンロード量が大きくなりモバイル回線で見た時のユーザ体験を損ねていました。

速いは正義ということで、速度改善の第一弾としてimgixの導入を決めました。 Lighthouseのスコアでも画像系の指摘が多くスコアが伸び悩んでいたのでこれを一つのKPIとして導入作業を進めました。

  • Properly size images 20s…
  • Serve images in next-gen formats 15s…

今回の移行で行ったこと

CloudFrontから配信していたサイズの大きな画像をimgixからの配信に切り替え、コンテンツダウンロード量を削減するために、移行と同時にクエリパラメータによる画像圧縮とリサイズ、フォーマット変更を行いました。

基本的なパラメータを下記にまとめたのでご参考までに。

内容 パラメータ 備考
サイズ圧縮 q=値 or auto=compress 動的に圧縮率を変更可能, autoの場合はデフォルトで75%の圧縮率
リサイズ w=値,h=値 動的にリサイズ可能
※fitパラメータで、縦横比維持、トリミング、また顔のズーム等にも対応しています。
画像フォーマット変更 auto=format 対応ブラウザ配信時にwebp対応

気になる方は、公式ドキュメント に細かく書かれているのでこちらをご覧ください。

下記のように、パラメータを付与するだけで一枚のオリジン画像から簡単にリサイズすることが出来ます。 ほぼ劣化なしにリサイズや圧縮出来る点がimgixの強みだなと個人的には感じています。

元画像 209KB

リサイズ画像(auto=format,compress&q=90&w=400) 32KB

導入後の成果

画像の最適化だけではスコアが劇的に上がるということはないのですが、下記を見ていただくとわかる通り画像系の課題が多かった関係で、一定のスコア向上を実現できました。

特に、今回の狙いだったコンテンツダウンロードサイズの削減が実現出来たことで、モバイル回線でママリを使ってくれるユーザのユーザ体験向上に寄与できた点が一番大きかったです。

コストに関しては細かくは書けないのですが、画像圧縮の結果配信量が減ったのでその分コストカットも実現出来ました。

Lighthouseの結果

そもそものスコアが低いという話はありますが、導入結果としてわかりやすいので参考として貼っておきます。

スコアという意味では、まだまだ改善の余地があるのでフロントエンドエンジニアと協力してより速さとその先にある快適なユーザ体験を追求していきたいと思っているのでまだ途上です。

  • 記事タブのwebview
項目 CloudFront imgix 差分
モバイル トータルコンテンツダウンロードサイズ 5551KB 807KB 85%減
パフォマンススコア 63 74 +11
コンテンツの初回ペイント 1.0s 0.9s -0.1s
意味のあるコンテンツの初回ペイント 3.4s 1.0s -2.4s
速度インデックス 4.7s 4.1s -0.6s
CPUの初回アイドル 6.7s 6.0s -0.7s
インタラクティブになるまでの時間 8.1s 6.7s -1.4s
入力の推定待ち時間 460ms 190ms -270ms
  • 記事ページ
項目 CloudFront imgix 差分
モバイル トータルコンテンツダウンロードサイズ 3682KB 1739KB 50%減
パフォマンススコア 29 44 +15
コンテンツの初回ペイント 1.7S 1.4s -0.3s
意味のあるコンテンツの初回ペイント 1.7s 1.4s -0.3s
速度インデックス 10.7s 6.0s -4.7s
CPUの初回アイドル 15.3s 11.0s -4.3s
インタラクティブになるまでの時間 21.9s 13.3s -8.6s
入力の推定待ち時間 160ms 140ms -20ms

導入メリット

導入メリットとして、下記が上げられます。

  • エンドユーザには、コンテンツダウンロードサイズの削減によるユーザ体験の向上を提供
  • アプリケーション的には、よく画像アップロードトリガで走らせたりする画像リサイズ処理をCDN側にオフロード出来る
  • コスト面でも、契約にはよりますがリサイズ等による配信量軽減によるコストダウン
  • 画像のリサイズを人力で行っているようなケースの場合は、その作業もすべてクエリパラメータベースに置き換えることが出来ます

注意点

最後に、imgix導入を検討する上で注意しておいた方がよい点についてもまとめておきます。

料金体系

Imgixは、Master Image数+帯域での課金になります。 Master Imageとはオリジナルのイメージ数のことで、これが無限に増えていくようなユーザアップロード用途で使うと思わぬコスト増を招く可能性があるので事前に検証してコスト計算しておくのがおすすめです。

TLS1.2未対応ブラウザへの対応

TLS1.1以前のSSL通信はサポート外なので、Androidのwebview標準ブラウザだと画像が表示されません。セキュリティ観点から世の中的には少なくなってきていますが、動作確認時にチェックするのがベターです。

サポートや営業とのやりとりは英語が必須

日本の代理店はないので、ボリュームディスカウントの交渉やテクニカルサポートはすべて英語です。ただ、とても親切に対応してくれるのであまりネックにはなりませんでした。

最後に

既に導入していた @akasakas に色々と情報をもらいスムーズに移行を進められたので、この場を借りてお礼を言いたいと思います。ありがとうございました。

コネヒトでは変化を恐れずに良いものを取り入れながらサービスの信頼性向上をミッションに一緒に働く仲間を探しています。 少しでも興味もたれた方は、是非気軽にオフィスに遊びにきていただけるとうれしいです。

www.wantedly.com

Droidcon Boston 2019に行ってきました!

f:id:tommy_kw:20190411215936j:plain

こんにちは!

Androidエンジニアの富田です。4/8、4/9にDroidcon BostonというAndroidエンジニア向けのカンファレンスがボストンで開催されました。国内のAndroidカンファレンスのブログは比較的多いと思うのですが、一方海外に目を向けると日本語ブログが少なく、どんなカンファレンス内容か気になることはないでしょうか?今回はDroidcon Bostonに参加してきましたので、気づきやナレッジを共有します。

Droidcon Bostonって?

www.droidcon-boston.com

Droidconとは、Androidエンジニア向けのグローバルなカンファレンスで、開発者同士のつながりを深めたり、技術の知見を共有するカンファレンスです。今回参加した開催地はボストンですが、それだけではなくニューヨークやロンドンなどでも開催されている大規模なカンファレンスです。

僕はDroidconに一度も参加したことがなかったのですが、DroidKaigiの登壇者、かつDroidcon Bostonスタッフでもある@droid_singhさんから‏幸運にもDroidcon Bostonのチケットを頂きましたので、初参加させて頂きました!色んな縁があるのだなとしみじみ感じたので、日々徳を積んでいこうと心に誓いました。

カンファレンス全般

Droidcon Bostonは2017年からスタートして、今年で第3回目となります。トラックは2つあり、トータル27トークセッションと4つのワークショップがありました。DroidKaigiと比べると参加者は若干少なく規模も小さめでしたが、立ち見をすることなくどのセッションでも座って落ち着いて見ることができました。

マルチトラックイベントにおいて、気になるセッションや時間を有効活用してセッションをみたいものですよね。そんな時に役立つのがカンファレンスアプリです。全体のスケジュール確認はもちろんのこと、気になるセッションが始まる前のプッシュ通知がくるので重宝しました。キャプチャではわからないのですが、カンファレンス当日には、アプリの最下部に「JUMP TO CURRENT」というボタンが表示され、それをタップすると進行中のセッションにスクロールされるようになっていました。こちらのカンファレンスアプリのソースコードも公開されているので、気になる方はご覧ください!

f:id:tommy_kw:20190413155603g:plain

カンファレンスの楽しみといえば無料でいただけるグッズですよね。ピンバッチやシールなど頂き、さらにこんな可愛いTシャツを頂きました!

f:id:tommy_kw:20190411215854j:plain
Droidcon Boston Tシャツ

また、全体を通して全てのセッションでライブスケッチを行なっていることに気づきました。下記のセッションを見ていただくと、登壇者の横に大きなボードがあるのがわかります。セッション開始と同時に下書きなしでセッション内容を描き始めます。

f:id:tommy_kw:20190411220750j:plain
Building @ speed of thoughtのセッション

そして実際に出来上がったスケッチがこちらです!60分枠のセッションがほとんどだったのですが、限られた時間でこのクオリティって...本当すごいですよね!セッション自体を見るのはもちろんですが、ライブスケッチを見るだけでも楽しめます。

f:id:tommy_kw:20190411221230j:plain
巨大なライブスケッチ

セッション一覧

セッション内容にはJetpack、Kotlin、テスト、Firebase、Flutter、Coroutine、RxJava、ML、アーキテクチャなど様々なジャンルで構成されていました。セッション一覧スライドに関しては以下のGithubにて管理されており、今年のセッションスライドだけでなく、20172018年分のセッションスライドもキャッチアップできるようになっています。ご興味ある方はぜひご覧ください!ここからは特に気になったセッションを3つ紹介します。

github.com

Do the Loco-MotionLayout: Building animations with MotionLayout

@mikescamellさんによるMotionLayoutの紹介です。MotionLayoutがどのように機能するか基礎についてサンプルコードを基に体系的に学ぶことができます。MotionSceneとは何か、またそれを利用して状態とレイアウトから分離する方法、トランジションのトリガーとなるクリックとスワイプの利用方法、KeyAttributesを利用してアニメーションの微調整方法などまで言及されていました。

f:id:tommy_kw:20190413151129g:plain
サンプルアプリ

Destination navigation: You’re going to love the transition

github.com

@emmaxさんによるNavigationアーキテクチャコンポーネントの入門紹介です。Android開発を加速するJetpackの一つであるのNavigationの利用方法について説明になります。基本利用からSafe Args、Conditional Navigation、Deep Link、テスト方法などまで言及されていました。

Leveling Up As An Android Dev

github.com

@moyheenさんによるAndroidエンジニアのキャリアについての紹介です。Android向けの技術カンファレスなので技術的な内容のセッションは多いですが、このセッションではキャリアについて紹介されています。Androidエンジニアの各レベルで求められていることって意外とわからないものですよね。今回紹介されていた内容は以下の通りです。

  • ジュニアエンジニア
  • ミドルエンジニア
  • シニアエンジニア
  • リードエンジニア
  • マネジメント
  • その他(GDEなど)

各レベルで何をすべきか、そして今のレベルを把握することによって、次のレベルに前進するための情報を得ることができます。

最後に

ひょんなことからDroidcon Bostonに参加させてもらったのですが、グローバルなカンファレンスであり、かつ豊富なジャンルのセッションでとても刺激的でした。スライド一覧を見ていただくと興味のある内容もあると思いますのでぜひご覧ください!また、Droidconはボストンだけでなく、様々な地域で開催されているため、Droidcon Bostonをきっかけに他のDroidconにも参加して行きたいと思います。以上になります、ありがとうございました!

新米マネージャーが1on1で実践していること

f:id:itosho525:20190409183944p:plain

こんにちは。サーバーサイドエンジニアの @itosho です。

Bリーグ(日本のプロバスケットボールリーグ)がシーズン佳境を迎え、週末はDAZN漬けの毎日を送っています🏀*1

というわけで、今日はバスケの1on1の話…ではなくミーティングの方の1on1の話をしたいと思います。僕は半年ほど前からプレイングマネージャーのようなポジションでマネジメント業務をしており、その中で1on1ミーティングも定期的*2に実施しています。

1on1については導入企業も増えてきており、事例も広く公開されてるようになってきましたが、まだまだ現場の個別具体的なノウハウは世に出てきていないと個人的には感じています。そこでこの記事では半年間の振り返りと知見の共有を兼ねて、僕が1on1で実施した取り組みを4つ紹介させていただきます。

なお、前職等でも多少のマネジメント経験はありますが、ガッツリやるのは初めて+コネヒトでは初めてのマネジメント経験になるので新米マネージャーという表現をさせていただいております。

1. 1on1の目的を共有

まず、初回の1on1では目的の共有を行いました。一口に1on1と言っても、社長が実施する1on1と直属の上長が実施する1on1は役割が違います。また、個々人が1on1に対して抱いているイメージや期待値も様々です。ですので、最初にそのギャップを埋めるために僕が想定している1on1の目的やイメージなどを伝えるようにしました。

具体的には以下の目的でやるよ!ということを共有しました。

## 1on1の目的
- 設定した目標を達成するための支援 
- 生き生きと働ける(≒その人が100%の力を発揮出来る)ようにするための支援
  - もやもやしていることや本当はやりたいこと何でもいいので話してください
- よろず相談
  - 会社関係なくキャリアのお悩みとかあれば(話したい人はプライベートの話でもOK)

また、これは雰囲気というかただのイメージの共有ですが、野球で例えると僕(メンター)は監督やコーチではなくキャッチャーでメンバー(メンティー)はピッチャーだよということを伝え、1on1はキャッチボールをするような場であることもセットで共有しました。

2. 1on1シートの作成

目的の共有と併せて、面談シートのような1on1シートを作成しました。個人的に1on1では雑談も大切だと思っているので、あまりガチガチにやりたくないと思っています。とは言え、やってる感だけ出して、目標の達成支援が出来ていないなら、それはメンバーの貴重な時間をいたずらに奪っているだけなので、トラッキングも兼ねて1on1の数日前に1on1シートを用意して事前に話したいことなどを書いてもらうようにしていました。また、僕からも気付いたことがあれば積極的に書くようにしていました。ただ、1on1を受ける側からすると準備のコストが高いと1on1が億劫になってしまうこともあるので事前に書くのは任意にしていました。

1on1シートのフォーマットは何度かアップデートを行い、現在は以下のような形で運用しています。

## YYYYMMDD: 第X回

### お話
- 事前に話したいことがあれば書いておいてください!

### プチ振り返り&フィードバック

#### よかったこと
- 最近よかったことや上手くいったことをお互い書くコーナー

#### よくなかったこと
- 最近よくなかったことや改善したほうがよいことをお互い書くコーナー

### Todo
- メンターの宿題を書くコーナー

簡単に説明すると、最初のお話枠は何でもよいので話したいトピックがあれば書いてもらっています。2つ目のプチ振り返り&フィードバック枠は日頃からカジュアルにフィードバック出来る場があったほうが良いかなと思い、メンバーが自分の行動でよかったと思うことやよくなかったと思うことを書き、僕はその人を傍から観察して、よかったと思うことやよくなかったと思うことを書くようにしています。基本的にはポジティブなフィードバックが多めですが、お互いに書き、それを共有することで期待値調整や認識齟齬の早期解消を行っています。最後のToDo枠は1on1の過程で発生した僕がやるべきタスクを忘れないようにメモします。ここで書いたタスクは次の1on1で進捗を報告したり、対応したタイミングで共有したりしています。

3. フィードバックワークの実施

コネヒトではOKRによる目標設定をしているのですが、その過程で中間振り返りを実施するタイミングがあります。そこで目標達成のためにいつも1on1より長めに時間を確保し、目標の振り返りと併せてワークショップ形式でフィードバックを行いました。

いわゆる、ジョハリの窓に近いようなワークなのですが、目的としては、

## フィードバックワークの目的
- 自身の振り返りと他者の振り返りを掛け合わせることで、気付きと学びを得る。
- そして、行動を変える一歩を踏み出すための後押しをする。

というのを掲げ、以下のような流れでワークを行いました。

## フィードバックワークの流れ

### 1. メンバーが以下の内容を付箋に書く
- 目標を意識して移せた行動や言動
- 目標を意識していたが出来なかった行動や言動

### 2. 僕が以下の内容を付箋に書く
- 目標に沿っていたと思う行動や言動
- もう少し目標に沿わせられたと思う行動や言動

### 3. それぞれの付箋を発表する
- 発表された付箋をメンバーが以下の画像のような四象限にマッピングする

### 4. マッピングされた付箋をみながら質問し合う
- 何故出来ないか深掘りしたりどうすれば出来るようになるか考えたり

### 5. 最後に今後注力したいポイントを1つ決める
- 決めたものは1on1シートに記載する

f:id:itosho525:20190409154121p:plain

やってみた所感としては、対面でやるフィードバックよりもコトに向かいやすい(僕のフィードバック力不足に依るところも多いですが)点が非常に良いなと感じました。

4. オフサイトでの実施

普段の1on1はオフィス内*3で行っているのですが、たまにカフェなどのオフサイトでも1on1を実施しています。もちろん、オフィス外なのでコンフィデンシャルな話は出来ませんが、いい意味で仕事っぽくない雰囲気になり、いつもと違う話が構造的にもやりやすいので時々オフサイトでやるのは良いなと思います。ちなみに事前に苦手な飲み物がないかどうかを確認しておくことも地味に大切です。

まとめ

このようにまとめると、ややもすればいい感じに1on1をやっているようにみえるかもしれませんが、まだまだ勉強不足で試行錯誤の毎日です。それでも、僕は1on1の質はメンバーのことを考えている量に比例すると思っているので、これからも日々努力を積み重ねていきたいと思っています。冒頭にも述べましたが、1on1の現場の個別具体的なノウハウはまだまだ世に出てきていないと感じています。それは最適解が会社や職種、個人、はたまたフェーズなどの変数によって大きく異なることに起因するのも原因の一つだと思います。しかし、だからこそ様々な事例を知ることも重要だと思うので、またノウハウが溜まってきたタイミングで定期的に共有を行っていきたいと考えています。この記事が誰かのためになれば幸いです。

*1:ちなみに当方、アルバルク東京のブースターです。

*2:基本的には隔週1回30分のペースで実施していますが、頻度は各人の状況や時期に応じて適宜見直しています。

*3:オフィスで実施する場合も、会議室っぽくないスペースかつ対面にならない場所を選ぶことが多いです。

PHPerKaigi 2019にシルバースポンサーとして協賛いたします!

こんにちは。サーバーサイドエンジニアの 高野 (@fortkle) です。
さて、今日はイベント協賛の告知をさせてください!

PHPerKaigi 2019に協賛いたします!

タイトルにもある通り、PHPerKaigi 2019 にシルバースポンサーとして協賛いたします。
コネヒトではメインプロダクトである「ママリ」を始めとして開発のメイン言語としてPHPを活用しており、フレームワークとしてはCakePHPを採用しています。

phperkaigi.jp

イベント概要

PHPerKaigiはどんなイベントか、公式サイトから拝借すると

PHPerKaigi(ペチパーカイギ)は、PHPer、つまり、現在PHPを使用している方、過去にPHPを使用していた方、これからPHPを使いたいと思っている方、そしてPHPが大好きな方たちが、技術的なノウハウとPHP愛を共有するためのイベントです。

という 過去・現在・未来PHPerに向けたお祭り のようです! 他のカンファレンスと同様に公募トークがありつつ、数人で特定のテーマについてディスカッションするInteractive Round Tableや、アンカンファレンスなどちょっと違ったことも企画されているとのこと!

タイムテーブルもすでに発表されているので興味がある方は要チェックです!

タイムテーブル | PHPerKaigi 2019 - fortee.jp

3日間にかけて行われる大規模なイベントなのでどのトークを聞こうか迷っちゃいますね。 個人的には、設計やアーキテクチャの話と、PhpStorm/コードリーディングまわりの話と最終日のLTが気になっています!

最後に

ここまで読んでくださった皆様、ありがとうございました。
そして、 PHPerチャレンジ中の皆様、お目当てのPHPerトークンはこちらです!

#EnjoyPHPWithConnehito

それでは!

コネヒトではPHPerを積極採用中です!

www.wantedly.com

「やさしいかんしのご提案」をしました 〜コネヒトなりの「監視の民主化」入門〜

こんにちは! @o0h_です。
3月は・・・王様ランキング!!!!おめでとうございます🎉

王様ランキング 1巻

https://cdn-mamari.imgix.net/authorized/5c92686d-9b58-410f-8b54-0037ac110003.jpg

さて、唐突に本題なのですが
先日、入門監視を読んで思ったこと・感じたことを当ブログに投稿しました。

tech.connehito.com

今回は、ちょっとした続編のようなものになります。

先の記事では、自分自身に生じた内省や「べき論」「目指すべき地点」を中心に取り扱いました。
具体的な「私や他のメンバーが取るアクション」や「変更されていく内容」についてはスコープにしておりません。

当然、こうもデカい口を叩いた以上は、実践をしていく必要があります。
でないと・・・ダサダサ君になってしまいますよね。
そんな訳で、「実際に組織を変えていくぞ」と、その最初の一歩目として 監視の民主化に向けたキックオフ を行いました。*1

先日のブログのような内容が「概念」「抽象」だとするなら、こちらは「実践」「具体」に相当するものでもあります。
折角ですので、私と同じような課題感を持った人と共闘すべく、この場で公開してみます!

あくまで社内向けに企画・作成した内容なので、「内輪ならコンテキストがあるから、ちゃんと伝わるだろうけどさ」な部分も少なくありません。
それでも、今回の内容はある程度の一般性を保てているのではないか〜なんて考えています。

*1:先日、弊社にて開催した勉強会での私の発表内容もこの内容を想起しながらまとめたものになります

続きを読む

Slack Block Kitを使って既存ツールをカッコよくしてみた

こんにちは、 BLUE GIANT SUPREME (7) (ビッグコミックススペシャル)を読みました。金城(@o0h_)です。
読後、へーしゃで称賛が発生していました。

f:id:o0h:20190303130444p:plain
こちら、社長と私です

そんな感じで色々にSlackを利用している身のものですが、先月「新しい機能をリリースしたよ!」という発表がありました。
「Block Kit」です。

Block Kitは、「Slack投稿の表現力を上げる」「ユーザーと、より気の利いたインタラクションをつなぐことを支援する」ための新UI(のためのAPI)です。
これを利用すると、いつものSlackの投稿がとても高機能になります。

実際に触ってみたので、使い方やハマったポイントなどを共有していきます。

https://cdn-mamari.imgix.net/authorized/5c7ccc81-7170-439c-8949-0034ac110003.jpg

続きを読む

React HooksとContextAPIでFluxをやってみる

f:id:dachi023:20190226162905p:plain

CTO室エンジニアの安達 (@dachi_023) です。React v16.8で待ちに待ったHooksが (20日前に) リリースされました。そんなHooksを使ってFluxやる時ってどうするんだろう?と思ったので調べて写経してみました。

reactjs.org

書いたコード

create-react-app して出てきたものをいじって作りました。Flux化するまでに書いたコードだけを見たい場合は コミットログ が分かりやすいかもしれません。

github.com

余談: 実際書いてみて「Hooksちゃんと理解してなかったなぁ、9割くらい写経だとしても覚えるために書くというのは良いことだ」と感じられました。

やってみる

  • お題: +1 / -1 ができるカウンターの実装
  • useReducer() とContextでStoreをつくる
  • Actionの発行 → dispatch → Stateの更新 → 再描画 をやる

Context

ContextがStateを管理するための入れ物 & 伝搬役になります。とりあえず createContext() して返します。今回はdispatchも同じContext内で管理します。

import { createContext } from 'react'

export default createContext({
  count: 0,
  dispatch: null
})

Reducer

Actionを受け取って新しいStateを返します。Actionの中身は redux-utilities/flux-standard-action と同様です。Reducerの定義は Reactのドキュメント にも書いてありますが (state, action) => newState です。

export default function CounterReducer(state, action) {
  switch (action.type) {
    case 'increment':
      return { count: state.count + 1 }
    case 'decrement':
      return { count: state.count - 1 }
    default:
      return state
  }
}

ActionCreator

外部通信やビジネスロジックがないのでほぼ無意味な感じになってますが前述したflux-standard-actionに倣ってActionを生成して dispatch() します。

export function increment(dispatch) {
  dispatch({
    type: 'increment',
    payload: {}
  })
}

export function decrement(dispatch) {
  dispatch({
    type: 'decrement',
    payload: {}
  })
}

Component

作ったものをつなげていきます。

App.js

useReducer() にCounterReducerとStateの初期値を渡してstateとdispatchを取り出しProviderに突っ込めばStateの生成と値の伝搬作業が完了します。

import React, { useReducer } from 'react'
import Counter from './Counter'
import CounterContext from './contexts/CounterContext'
import CounterReducer from './reducers/CounterReducer'
import './App.css'

export default function App() {
  const [state, dispatch] = useReducer(CounterReducer, { count: 0 })
  return (
    <div className="App">
      <header className="App-header">
        <CounterContext.Provider value={{ ...state, dispatch }}>
          <Counter />
        </CounterContext.Provider>
      </header>
    </div>
  )
}

Counter.js

の処理でProviderにセットしたStateを useContext() で取り出し表示します。Stateと一緒に入れてあるdispatchを取り出してクリックイベントに仕込めばStateの更新処理までが完了です。

import React, { useContext } from 'react'
import CounterContext from './contexts/CounterContext'
import { increment, decrement } from './actions/CounterActions'

export default function Counter() {
  const { count, dispatch } = useContext(CounterContext)
  return (
    <>
      <h2>{count}</h2>
      <button onClick={() => increment(dispatch)}>Increment</button>
      <button onClick={() => decrement(dispatch)}>Decrement</button>
    </>
  )
}

できあがったのがこれ

ちゃんと増えたり減ったりするようになりました!

f:id:dachi023:20190226160647g:plain

まとめ

  • 今までのClassベースのComponentとは書きっぷりがだいぶ異なるので最初とっつきづらいのかもなと思いました、1回でも真面目にやると「なんだ全然できるじゃん!」という感じですが。
  • 複雑なことしないのであればFluxライブラリなど使わずにHooksで実装しちゃってもいいかもしれないですね。結構使えそうじゃないかな?と思ってます。

参考記事