LoginSignup
4
6

More than 1 year has passed since last update.

React歴4ヶ月で本のレビューサービスをリリースした

Last updated at Posted at 2022-04-30

はじめに

所属する会社が提供しているサービスでReactを使っており、私はカスタマーサクセスなのでガチエンジニアではないけどもトラブルシューティングや仕様の理解でソースを読むべき機会は多々ありました。ベンチャー企業でもあり、エンジニアのリソースが限られていることから、より業務範囲を広げるため、また、エンジニアとのよりスムーズなコミュニケーションのために言語理解を深める必要がありました。

バックエンドの実装やAIモデルの構築等はそれなりに経験があるものの、フロントエンドはほぼ未経験(とはいえ、宣言的なプログラム言語でいうとFlutterは少しだけ書けるので、全くの素人よりは多少のアドバンテージがあるかもしれません)であっため、必要に迫られて2022年の後半からReactを勉強し始めました。その過程で自分のサービス作れそうだな! 作りたいな! という気持ちになり、サービスを作りながら本ページを記載しています。

バックエンドまで作り込みたかったのですが、平日は本業が忙しく、ほぼ週末の限られた時間で開発しているため、一旦はAWS Amplifyで手抜きしました(といってもAmplify自体もさほどかんたんではないです)。

免責事項

  • React・Javascript経験はたかだか数ヶ月程度なので内容に誤りがありましたらドシドシ(でもやさしく)ご指摘ください
  • 本ページは所属と一切関係なく、個人の学習のために作成したものとなります

本記事のモチベーション

上述のとおり、フロントエンドはさっぱりな私でも、書籍等で学習しながら、AmplifyというBaaSを用いて比較的短期間でサービスを立ち上げることができました。

まだまだ本格的に皆様に提供できれレベルにないことは100も承知なのですが、誰もがものづくりに参加できる時代に、ぜひ、ものづくりの楽しさをしってもらいたいと思い記載しております。

ただし、少し厳しい事を言うと、本のタイトルにありがちな「誰でも1日で~」みたいなものは、自由度の高いサービスを開発したいであればあまり期待されない方が良いのかなと思っています。Amplifyを使っても、トラブル起こりまくりです。

開発・運用を継続することは楽なことではありません。それでも粘り強く、楽しんで取り組める人はきっとものづくりの本当の楽しさにたどり着けるのではと考えております。このような記事の発信を通じて、これからがんばろうという人々の助けになったり、ものづくりを楽しんでいる人々と繋がれたらうれしぃなあと考えております。

よろしければTwitterFacebookでもつながってください! 一緒に開発してくださる方、英語学習や読書が好きな方、飲み友になってくれる方も募集中ですw

成果物

いろいろなフィルターによりいろいろなグループで本を紹介しあえるサイト

※まだまだ全然未完成です。これからブラッシュアップしていきますm(_ _)m

開発しながら思ったこと

  • アイデアだけ練っているだけでは何も始まらない、そんなことやってるやつはうじゃうじゃ存在する

    • 逆にそこからきちんと形にする、動けるやつは案外少ないのではないか
  • 改善は継続的に(グロースが一番大変であり、ここはこのサイトもこれから苦労することになるはず)

  • 鉄は熱いうちに打て(モチベーション持続期間の観点から、MVPをある程度仕上げるまでは短期間に実装することをおすすめする)

  • モチベーションを保つために同僚や友人に見せてドヤるとよい(やり過ぎるとたぶんひかれる・・・)

  • ソフトウェアでもハードウェアでも、フロントエンドでもサーバーサイドでも、ものづくりは楽しい

開発の進め方

一人なので大したことはしてません。コード書いてはコミット→GithubにPushの繰り返し。

ある程度作ったら、近所のイケメンお兄さんに見てもらって、いろいろと意見をもらって修正修正また修正。

タスク・進捗管理はTrelloを使いました。
Cursor_と_個人開発___Trello-9737807.png

出会った本たち

react-book.jpg
この他に以下の本に軽く目を通しました。

りあクト! 本は出先で読むには表紙が恥ずかしいんですが、内容は素晴らしいものでした。ただ、初心者には少しむずかしいので、私のような素人さんには、「モダンJavaScriptの基本から~」本と「React実践ハンズオン」本から読み始めることをおすすめします。「CSS設計」本はCSSも素人な私にとっては早すぎました… ただ、CSSはマジで設計を考えないとぐちゃぐちゃになるので、そのあたりの考え方はとても参考になりました。

サービスを作る上で学んだこと一覧

ここからは細かい開発手法なりReactの技術要素について記載します。

プロトタイピング

様々な手法やツールがありますが、私はiPadのGoodNotesを使って画面デザインのラフスケッチ(と呼べるレベルではないただのラクガキ)やDBのテーブル設計等を行いました。仕事としてちゃんとやるならFigmaのようなプロトタイピングツールでも使ったほうが良いんでしょうが、そこの学習コストもそれなりに掛かり、デザインセンスも壊滅的であることを考えると私には暫くはこれで良いように感じました。
プロトタイプ.jpeg

本検索で利用したAPI

Google Books APIsを使いました。本の登録数が少ないとのことですが、まぁ一旦は他に良いものがなさそうなので良しとします(後々、自分で本を登録できる機能を作る予定です)。

Hook

React Router

React-hook-form

フォーム作りたかったらとりあえず使っときましょう。自前でゴリゴリ書くより、だいぶシンプルに記載できると思います。

デザイン、レイアウト

レンダリング

サービスのコードが大したこと無いうちはさほど問題にならないかもしれませんが、それなりの規模になってくるとpropsでコンポーネントのサブツリーにデータをバケツリレーで渡すことが限界になってcontextやreduxについて調べたり、レンダリング起こしまくってmemo化含む再レンダリング抑止の仕組みを調べたりすることがあると思います。その際には以下のリンクが役に立ちます。

  • Reactのレンダリングに関する完全ガイド - Qiita https://qiita.com/hellokenta/items/6b795501a0a8921bb6b5
    • 状態管理についてはいきなりreduxとか使うよりまずはcontextを理解することからかなと思います。
    • memo化は再レンダリング抑止にパーフェクトな手法ではないけど、した方が良いよね。
      • ただし、propsの比較においてはjavascriptのオブジェクトの比較を理解しておく必要あり。
      • Contextプロバイダ直下のコンポーネントではmemo化しとけ、と記載があります。
        • ただし、memo化によるオブジェクト比較にもそれなりのコストが掛かることは知っておくべき模様です。

状態保持-応用-

とりあえずRedux使っとけば良いんではないでしょうか。

流れ的には、

  1. 状態の貯蔵庫であるストアを作る。

    // app/store.js
    import { configureStore } from '@reduxjs/toolkit'
    
    export const store = configureStore({
      reducer: {},
    })
    
  2. 作ったストアでReact Appを囲む(React Appの中でストアに蓄積した値を使えるようにする)。

    import { store } from './app/store'
    import { Provider } from 'react-redux'
    
    ReactDOM.render(
      <Provider store={store}>
        <App />
      </Provider>,
      document.getElementById('root')
    )
    
  3. 更新する対象毎(対象とは、例えば、ログイン情報、カウンターの値、いいね!の値など)にスライスを作る。スライスの中にはReduxで保持したい変数の初期値と、その更新方法をアクションとして定義する。

    import { createSlice } from '@reduxjs/toolkit'
    
    const initialState = {
      value: 0,
    }
    
    export const counterSlice = createSlice({
      name: 'counter',
      initialState,
      reducers: {
        increment: (state) => {
          // Redux Toolkit allows us to write "mutating" logic in reducers. It
          // doesn't actually mutate the state because it uses the Immer library,
          // which detects changes to a "draft state" and produces a brand new
          // immutable state based off those changes
          state.value += 1
        },
        decrement: (state) => {
          state.value -= 1
        },
        incrementByAmount: (state, action) => {
          state.value += action.payload
        },
      },
    })
    
    // Action creators are generated for each case reducer function
    export const { increment, decrement, incrementByAmount } = counterSlice.actions
    
    export default counterSlice.reducer
    
  4. store.jsを作ってスライスreducer関数をインポートし、ストアに追加する。reducerパラメータ内にフィールドを定義することで、このスライスのreducer関数を使用してその状態のすべての更新を処理するようにストアに指示することができる。

  5. ここまで出来たら利用の準備は完了。Reduxで扱いたい変数を展開するjs/jsx/tsxファイルのなかでuseSelector を使ってストアからデータを読み、useDispatch を使ってアクションをディスパッチする。

    import React from 'react'
    import { useSelector, useDispatch } from 'react-redux'
    import { decrement, increment } from './counterSlice'
    
    export function Counter() {
      const count = useSelector((state) => state.counter.value)
      const dispatch = useDispatch()
    
      return (
        <div>
          <div>
            <button
              aria-label="Increment value"
              onClick={() => dispatch(increment())}
            >
              Increment
            </button>
            <span>{count}</span>
            <button
              aria-label="Decrement value"
              onClick={() => dispatch(decrement())}
            >
              Decrement
            </button>
          </div>
        </div>
      )
    }
    

    ちなみに、非同期処理を書きたいときはToolkitに組み込まれているRedux thunkを使う。使い方は以下のとおり。

AWS

Amplify

認証周りはAmplify UI v1だとデザイン等、自由度が低いので、最初からv2を使うことをおすすめします。私のように時間を無駄にすることになります^^;

AppSync&GraphQL&DynamoDB

まずMVPを仕上げたかったため、バックエンドはAWS Amplifyを使って楽しました。Amplifyでは、AppSyncというGraphQLをかんたんに使えるようにしてくれるサービスを用い、私のように初心者でもかんたんにスキーマの定義やクエリの記述が可能です。Amplifyを使う方でGraphQLに知見のない方は、一度、以下に目を通すことをおすすめします。

Cognito

まったく知らないわけにもいかないのがCognito。どのような仕組みで動いているかはなんとなくでも知っておくべきでしょう。

ユーザープール、IDプール、トークン周り基本的な概念は頭に入れておいた方がトラブルシューティングにも強くなれると思います。

この他、IAMやDynamoDBなどは基本的な知識だけでも押させておくと、トラブったときにテンパらなくて良いと思います。知っておかないと死ぬ知識ではないですし、他に良い記事が死ぬほどあるので、ここでは詳細は割愛します。

外部認証プロバイダー
  • Google

    • [こちら](The Complete Guide to Implement Social Login With AWS Amplify https://www.prplbx.com/resources/blog/social-login-with-aws-amplify-guide/)を参考に実装。

      • ただし、めっちゃハマった。やり方自体はネットにいろいろ転がっているが、もっともハマったのはリダイレクト先の設定。
      • aws-exports.jsのリダイレクトの設定がなんど直接書き換えてもamplify push/pullすると元に戻ってしまう。
      • こんなときはcliでの設定が誤っている可能性があるため、/amplify/backend/auth/プロジェクト名/parameters.json のoAuthMetadataに書かれている内容とcli-inputs.jsonに記載の内容をダイレクトに書き換えると成功した。cliからリダイレクト先は追加・編集はできても削除はできない模様。

その他

実装のテクニック

  • code sandboxから実装例をパクる(ただしロジックを理解していないと応用も効かないため、後々弄る可能性があるのならコードを理解すること)
  • AmplifyもReactもどんどん新しい/優れた実装がでるため、下手にQiiitaとか参照するよりは公式ドキュメントを読んだほうが早い場合が多い

はまったときは

  • teratail【テラテイル】|ITエンジニア特化型Q&Aサイト https://teratail.com/

  • useEffectの第一引数にasync関数を直に掛けないよ! これめっちゃハマりました。

  • Amplify

    • Amplify Japan User Group

      何回か助けていただきました。若干、過疎ってますが… 盛り上がって欲しい。

    • Amplifyはバックエンドのデプロイでハマりやすい印象。ハマった場合、あまりにトラブルシューティングに時間がかかるようであれば1から作り直したほうが早い場合が多い(トラブルシューティングには結局、それなりにAWSの知識が必要になる)

    • GraphQLの401 {errorType: "UnauthorizedException", message: "You are not authorized to make this call.} がでた際は恐らくAPIキーの認証期限切れ

      • AppSyncの画面に行ってAPIキーの期限を延長する必要あり

      • デフォルトでは7日間で期限切れとなるため、amplify update apiで変更する必要あり

        参考) Amplify CLIでAppSync APIキーの有効期限を延長する方法 | まむんがITブログ https://mamunga.com/amplify-cli-appsync-api-key

    • 認証画面あたりをいじる際には「@aws-amplify/ui-react」のバージョン1と2でけっこう差異があるため、2へのバージョンアップには多少の書き換えが必要

    • reactのv17からv18も軽い気持ちでアップデートするとnode_modulesの依存関係で軽く死ねるので注意すること

  • 画像が表示されない

  • [WARN read-shrinkwrap This version of npm is compatible with lockfileVersion@1, but package-lock.json was generated for lockfileVersion@2. I'll try to do my best with it!]みたいなエラーが出る

その他知っておいた方が良い知識

  • パッケージ管理上必須知識
  • ググり方
    • 抽象化して調べることができるようにしておく
      • 極論的な例えだが、例えば、自身のファイルパスなどが含まれたエラーメッセージをGoogleの検索ボックスに入れてもろくな回答を得られないことと同様に、細微な情報を含めて検索すると本質的な回答に辿り着かないことが多い(経験論)
  • パクり方
    • それっぽいワードで日本語を混ぜずに英語だけでググる
    • code sandboxのサンプルソースが出てくるので、ある程度、読んで理解したうえでアレンジを加えてパクる

此処から先は少し高度なので一旦MVPができたあとで良い

最後に

サービスを作ってみて思うことは、率直に自分が考えたアイデアを形にするのはとても楽しいことだと思いました。同時に、普段、開発のメンバがいかに大変な思いをして改善を続けてくれているのかもわかり、感謝や尊敬の念も深まりました。

今回は開発の知識を深めたので、開発サイドのメンバとより円滑な意思疎通ができれば良いなと思いますが、CSの役割としては組織の活動を全方位的に円滑にすることも含まれていると思いますので、経営や営業の知識も絶えず吸収していきたいなと思いました。

最後に、本サービスはまだ全然未完成ですし、Reactの知識もまだまだこれからです。AWS等インフラ知識もより高める必要があります。これら全てにより磨きをかけるため、サービスも本記事の内容も、都度、アップデートできればと考えております。

皆様のお時間を本記事に割いていただきどうもありがとうございました。

4
6
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
6