- 投稿日:2019-05-30T20:07:37+09:00
reduxに疲れたのでunstated-next を試してみた
0. 概要
毎回Reactでアプリを作ろうとするたびに、
reduxに精神をやられています。確かに堅牢だし、チーム開発に向いているかもしれないけど、記述量と学習コストが大きすぎる・・・。いろいろ調べているうちにunstated-nextというライブラリを発見したので、試してみました。
型付きじゃないと夜も眠れないタイプの人間なので、TypeScriptで実装しています。1. 想定している読者
create-react-appでアプリケーションを作ったことがある人React Hooksに興味のある人TypeScriptがなんとなく分かる人reduxに疲れている人
React Hooksについては公式サイトの記事が充実しているのでそちらを参照してください。2. 準備
2.1 プロジェクトの作成
カウンター値をボタンで操作したり表示したりする簡単なアプリケーションを作ってみます。
まずは
npx create-react-appでサクッと React プロジェクトを作成。後ろに--typescriptを付けると、TypeScript のプロジェクトになります。# プロジェクトの作成 create-react-app sample --typescript # プロジェクトに移動 cd sample2.2 パッケージのインストール
今回使うのは
unstated-nextだけです。npm install unstated-next -S3. 実装
3.1 全体像
コードの説明の前に、全体像を載せてみます。矢印がデータやイベントの流れを示しています。
unstated-nextで登場するのは、2つだけです。
- ステート(カウンター値)の管理・操作方法を提供する
コンテナ- ステートの値を画面に表示させたり、イベントを受け渡す
コンポーネントただし、コンポーネントは元々Reactにあるコンポーネントのことなので、実質覚えるのはコンテナの部分だけ。簡単!
それでは以上を踏まえて、全体コードをご覧ください。
CounterContainer.ts (コンテナ)import { useState } from "react"; import { createContainer } from "unstated-next"; /** * カウンター操作用コンテナのHooks */ const useCountContainer = () => { // カウンターの数値と、数値更新用の関数を取得する const [count, setCount] = useState<number>(0); /** * カウンタを加算する * @param amount 加算する量 */ const add = (amount: number) => { setCount((count) => count + amount); }; /** * カウンタをリセットする */ const reset = () => { setCount(0); }; return { count, add, reset }; }; /** カウンター操作用コンテナ */ export const CounterContainer = createContainer(useCountContainer);CounterComponent.tsx (コンポーネント)import React from "react"; import { CounterContainer } from "./CounterContainer"; /** * カウンター操作用コンポーネントのプロパティ */ interface CounterOperateProps { /** 増減量 */ amount: number; } /** * カウンター操作用コンポーネント */ const CouterOperate: React.FC<CounterOperateProps> = (props) => { const counterContainer = CounterContainer.useContainer(); const onClick = () => { // 増減量の分だけカウンターを増やす (or 減らす) counterContainer.add(props.amount); }; return <button onClick={onClick}>amount : {props.amount}</button>; }; /** * カウンターリセット用コンポーネント */ const CouterReset: React.FC = () => { const counterContainer = CounterContainer.useContainer(); const onClick = () => { // 増減量の分だけカウンターをリセットする counterContainer.reset(); }; return <button onClick={onClick}>リセット</button>; }; /** * カウンター表示用コンポーネント */ const CouterDisplay: React.FC = () => { const counterContainer = CounterContainer.useContainer(); return <div>count : {counterContainer.count}</div>; }; /** * カウンターコンテナの提供用コンポーネント */ export const CounterComponent: React.FC = () => { return ( <CounterContainer.Provider> <CouterOperate amount={1} /> <CouterOperate amount={10} /> <CouterOperate amount={-1} /> <CouterReset /> <CouterDisplay /> </CounterContainer.Provider> ); };3.2 コンテナについて
先に述べた通り、コンテナではステートの管理とステートを操作する関数を提供します。
まず必要になるのが、React Hooksの定義です。これは
unstated-nextの機能ではないのでReact Hooks公式サイトの説明をご参照ください。やってることはこれだけです。
useStateによりHooks内にステートの値とそれを操作する関数(setCount)を取得するsetCountをラップしたadd関数とreset関数を定義する。- 戻り値としてコンテナ外で使いたい値や関数を返す。
CounterContainer.ts/** * カウンター操作用コンテナのHooks */ const useCountContainer = () => { // カウンターの数値と、数値更新用の関数を取得する const [count, setCount] = useState<number>(0); /** * カウンタを加算する * @param amount 加算する量 */ const add = (amount: number) => { setCount((count) => count + amount); }; /** * カウンタをリセットする */ const reset = () => { setCount(0); }; return { count, add, reset }; };Hooksが出来上がったら、
unstated-nextからimportしたcreateContainerでコンテナを作成します。CounterContainer.ts(続き)/** カウンター操作用コンテナ */ export const CounterContainer = createContainer(useCountContainer);3.3 コンポーネント側での利用
コンテナを利用するには2つの手順が必要です。
まず1つは、Providerによって、下位コンポーネントでコンテナを扱えるようにすることです。
サンプルでは、<CounterContainer.Provider>の部分がそれです。これによってCouterOperateやCouterDisplayがコンテナに触れるようになっています。CounterContainer.tsximport { CounterContainer } from "./CounterContainer"; // (中略) /** * カウンターコンテナの提供用コンポーネント */ export const CounterComponent: React.FC = () => { return ( <CounterContainer.Provider> <CouterOperate amount={1} /> <CouterOperate amount={10} /> <CouterOperate amount={-1} /> <CouterReset /> <CouterDisplay /> </CounterContainer.Provider> ); };次が、
useContainerによるコンテナの読み込みです。
コンポーネント内でCounterContainer.useContainer()を呼び出すことによって、コンテナの定義時に作成したHooksの戻り値であるcountの値や、add関数、reset関数に触れるようになります。CounterContainer.tsx/** * カウンター操作用コンポーネント */ const CouterOperate: React.FC<CounterOperateProps> = (props) => { const counterContainer = CounterContainer.useContainer(); const onClick = () => { // 増減量の分だけカウンターを増やす (or 減らす) counterContainer.add(props.amount); }; return <button onClick={onClick}>amount : {props.amount}</button>; }; /** * カウンターリセット用コンポーネント */ const CouterReset: React.FC = () => { const counterContainer = CounterContainer.useContainer(); const onClick = () => { // 増減量の分だけカウンターをリセットする counterContainer.reset(); }; return <button onClick={onClick}>リセット</button>; }; /** * カウンター表示用コンポーネント */ const CouterDisplay: React.FC = () => { const counterContainer = CounterContainer.useContainer(); return <div>count : {counterContainer.count}</div>; };4 まとめ
「いやこれ、ステートの管理をコンポーネントの外に出しただけジャン」と思われるかもしれません。実際その通りです。
ただ、どのコンポーネントでもプロパティを介さずにグローバル変数のようにコンテナを扱うことガできるのは大きな利点です。「ステートを外に出しただけ」なので学習コストもかなり低いです。React Hooks自体に制約が多いのでそちら側の慣れは必要ですが、制約に反した書き方をすると警告が出るようになっているのでミスには気づきやすいかと思います。
reduxに比べて発展途上のライブラリではありますが、記述量の少なさに感動することひとしおです。お試しあれ。
(不勉強なところが多いので、ご指摘よろしくお願いします)
- 投稿日:2019-05-30T16:16:50+09:00
Babelを用いた超最低限のReactのコンパイル環境の構築手順
備忘録として残します。
npmは入ってる前提。
■やり方
初期化コマンドでpackage.jsonを作成
#npm init でいくつか質問されるが面倒なので-yオプションでとりあえず全てYesで答えて自動作成 npm init -yトランスパイラ(バベル)インストール
npm install --save-dev babel-cli上記コマンド実行後、package.jsonの「devDependencies」に「babel-cli」が追加されていればトランスパイラのインストール完了
package.json{ "name": "name", "version": "1.0.0", "description": "", "main": "index.js", "scripts": { "test": "echo \"Error: no test specified\" && exit 1" }, "keywords": [], "author": "", "license": "ISC", "devDependencies": { "babel-cli": "^6.26.0" } }React関係のプラグインをインストール
#babel-preset-react #babel-preset-es2015 #babel-preset-stage-2 npm install --save-dev babel-preset-react babel-preset-es2015 babel-preset-stage-2
babel-preset-reactbabel-preset-es2015babel-preset-stage-2の3つのプラグインのインストールが完了package.json{ "name": "name", "version": "1.0.0", "description": "", "main": "index.js", "scripts": { "test": "echo \"Error: no test specified\" && exit 1" }, "keywords": [], "author": "", "license": "ISC", "devDependencies": { "babel-cli": "^6.26.0", "babel-preset-es2015": "^6.24.1", "babel-preset-react": "^6.24.1", "babel-preset-stage-2": "^6.24.1" } }コンパイルするプリセットを「.babelrc」に登録する。
ちなみにwindowsで「.」始まりのファイル名にする場合は.ファイル名.でリネームできます。.babelrc{ "presets": ["react", "es2015","stage-2"] }あとちょっとで終わりです。
次にトランスパイル用のコマンドを用意。
今回は手動コンパイル用と、ファイルの更新を監視して自動コンパイルしてくれる用の2つ用意します。
後者はIDEでコーディング用です。
いちいちjsx編集→手動コンパイル→ブラウザで動作確認はさすがに面倒ですので。package.json{ "name": "name", "version": "1.0.0", "description": "", "main": "index.js", "scripts": { "build": "babel ビルド元フォルダパス -d ビルド先フォルダパス", "buildauto": "babel -w ビルド元フォルダパス -d ビルド先フォルダパス" }, "keywords": [], "author": "", "license": "ISC", "devDependencies": { "babel-cli": "^6.26.0", "babel-preset-es2015": "^6.24.1", "babel-preset-react": "^6.24.1", "babel-preset-stage-2": "^6.24.1" } }これで完了です。
後は下記コマンドを実行すればコンパイルできます。#手動 npm run build#自動 #ファイルの変更を監視して、自動コンパイルしてくれます。 #コーディング中はこれで。 npm run buildauto当然ですがコンソールが開いている間だけ自動コンパイルしてくれます。
以上です。
- 投稿日:2019-05-30T16:16:50+09:00
超最低限のReactのコンパイル環境の構築手順
備忘録として残します。
npmは入ってる前提。
■やり方
初期化コマンドでpackage.jsonを作成
#npm init でいくつか質問されるが面倒なので-yオプションでとりあえず全てYesで答えて自動作成 npm init -yトランスパイラ(バベル)インストール
npm install --save-dev babel-cli上記コマンド実行後、package.jsonの「devDependencies」に「babel-cli」が追加されていればトランスパイラのインストール完了
package.json{ "name": "name", "version": "1.0.0", "description": "", "main": "index.js", "scripts": { "test": "echo \"Error: no test specified\" && exit 1" }, "keywords": [], "author": "", "license": "ISC", "devDependencies": { "babel-cli": "^6.26.0" } }React関係のプラグインをインストール
#babel-preset-react #babel-preset-es2015 #babel-preset-stage-2 npm install --save-dev babel-preset-react babel-preset-es2015 babel-preset-stage-2
babel-preset-react、babel-preset-es2015、babel-preset-stage-2の3つのプラグインのインストールが完了package.json{ "name": "name", "version": "1.0.0", "description": "", "main": "index.js", "scripts": { "test": "echo \"Error: no test specified\" && exit 1" }, "keywords": [], "author": "", "license": "ISC", "devDependencies": { "babel-cli": "^6.26.0", "babel-preset-es2015": "^6.24.1", "babel-preset-react": "^6.24.1", "babel-preset-stage-2": "^6.24.1" } }コンパイルするプリセットを「.babelrc」に登録する。
ちなみにwindowsで「.」始まりのファイル名にする場合は.ファイル名.でリネームできます。.babelrc{ "presets": ["react", "es2015","stage-2"] }あとちょっとで終わりです。
次にトランスパイル用のコマンドを用意。
今回は手動コンパイル用と、ファイルの更新を監視して自動コンパイルしてくれる用の2つ用意します。
後者はIDEでコーディング用です。
いちいちjsx編集→手動コンパイル→ブラウザで動作確認はさすがに面倒ですので。package.json{ "name": "name", "version": "1.0.0", "description": "", "main": "index.js", "scripts": { "build": "babel ビルド元フォルダパス -d ビルド先フォルダパス", "buildauto": "babel -w ビルド元フォルダパス -d ビルド先フォルダパス" }, "keywords": [], "author": "", "license": "ISC", "devDependencies": { "babel-cli": "^6.26.0", "babel-preset-es2015": "^6.24.1", "babel-preset-react": "^6.24.1", "babel-preset-stage-2": "^6.24.1" } }これで完了です。
後は下記コマンドを実行すればコンパイルできます。#手動 npm run build#自動 #ファイルの変更を監視して、自動コンパイルしてくれます。 #コーディング中はこれで。 npm run buildauto当然ですがコンソールが開いている間だけ自動コンパイルしてくれます。
以上です。
- 投稿日:2019-05-30T14:58:34+09:00
【React, redux, redux-saga】typesafe-actionsでコード量を減らそう
はじめに
reduxのAction周りの型をしっかり付けようとすると、どうしてもコード量が多くなってしまいます。
さらに、redux-sagaを使って副作用を実装する場合は、副作用ごとにrequest、success、failureの3ケースについてActionとActionCreatorを定義する必要があるため大変です。
この悩みを解決するために、本稿ではtypesafe-actionsというライブラリを使って少ないコードでしっかり型をつける方法を紹介します。題材にするコード
今回はYouTube Data APIを利用して、動画を検索できるクライアントアプリを題材に説明していきます。
コードはこちら実装内容
今回は入力されたテキストから動画を検索する機能をredux-sagaを用いて実装していきます。
これをredux-sagaのフローに分けると以下のようになります。
- 検索ボックスにテキストを入力してsubmitしたらAPIを叩く(REQUEST)
- 正常に値を受け取れた場合、Storeに保存する(SUCCESS)
- レスポンスが空だった場合エラーを投げる(FAILURE)
ActionType, ActionCreator, Actionの実装
まずはActionTypeを定義します。
actions/Video/VideoActionType.tsenum VideoActionType { SEARCH_VIDEOS_REQUEST = "SEARCH_VIDEOS_REQUEST", SEARCH_VIDEOS_SUCCEEDED = "SEARCH_VIDEOS_SUCCEEDED", SEARCH_VIDEOS_FAILED = "SEARCH_VIDEOS_FAILED", } export default VideoActionType;続いて、ActionCreatorを実装します。ここで、
typesafe-actionsの出番です。
createAsyncActionを利用することで、簡単にActionCreatorを定義できます。actions/Video/VideoActionCreator.tsimport VideoActionType from './VideoActionType'; import SearchListResponse from '../../states/SearchListResponse'; import { createAsyncAction } from 'typesafe-actions'; export const searchVideos = createAsyncAction( VideoActionType.SEARCH_VIDEOS_REQUEST, VideoActionType.SEARCH_VIDEOS_SUCCEEDED, VideoActionType.SEARCH_VIDEOS_FAILED )<string, SearchListResponse, Error>();以下の3つのActionCreatorをまとめて生成することができました。
-searchVideos.request(payload: string)
-searchVideos.success(payload: SearchListResponse)
-searchVideos.success(payload: Error)それぞれのメソッドは、引数で指定した
typeとジェネリクスで指定した型のpayloadを返します。payloadがいらない場合はジェネリクスの該当部分にundefinedを指定しましょう。素のTypeScriptだけで実装する場合、以下のように1つずつ定義する必要があるので、だいぶ楽ですね。
no-typesafe-actions.tsfunction request(payload: string) { return { type: VideoActionType.SEARCH_VIDEOS_REQUEST, payload, }; } function success(payload: SearchListResponse) { return { type: VideoActionType.SEARCH_VIDEOS_SUCCEEDED, payload, }; } function failure(payload: Error) { return { type: VideoActionType.SEARCH_VIDEOS_FAILED, payload, }; }最後にActionCreatorがReturnするActionオブジェクトも定義しましょう。
ここではtypesafe-actionsのActionTypeを使うことでsearchVideosが持つ3つのActionCreatorがReturnするActionオブジェクトを1つのunion型にまとめることができます。
この型は、Reducerの引数action: VideoActionやcontainerのmapDispatchToPropsの引数dispatch: Distatch<VideoAction>のように使用します。actions/Video/VideoAction.tsimport { ActionType } from "typesafe-actions"; import * as ActionCreators from "./VideoActionCreator"; type VideoAction = ActionType<typeof ActionCreators>; export default VideoAction;saga
後日追記
おわりに
typesafe-actionsには他にも便利なユーティリティがたくさんあるので、ぜひ使ってみてください。
あまり時間が取れず急いで書いたので、今後も追記や修正をしていきます。
- 投稿日:2019-05-30T11:36:12+09:00
Ionic CLIでReactが使えるようになりました
本日、Ionic CLI 5.0.0がリリースされまして、Ionic CLIでReactプロジェクトを扱えるようになりました。
https://github.com/ionic-team/ionic-cli/releases/tag/ionic%405.0.0$ npm install -g ionicでインストール可能です。Ionic CLIは
npxでローカルで扱うこともできるのですが、多くの場合はグローバルにインストールして扱うことが多いです。インストールが終了したら
$ ionic start --type=reactでIonicのReactプロジェクトを作成することができます。4つテンプレートが用意されているので、この中から自分にあったものを選択するようにしてください。
❯ blank | ブランク(空白ページのみ)のスタータープロジェクト sidemenu | サイドメニューナビゲーション(ハンバーガーメニュー)があるプロジェクト tabs | タブが用意されているプロジェクト conference | デモプロジェクト実装方法などをみるのには、conferenceが一番適してるかと思います。よーしつくるぞ!!という時は、それ以外のものを選択してください。
具体的にどういうReactプロジェクト?
Create React Appと同様の構成で、React Router v4を採用しています。react-scriptsが使われています。
あと、デフォルトがTypeScriptとなっているので、そこだけ注意が必要かなーという感じです。App.tsxはこんな感じ。starters/react/official/blank/src/App.tsximport React from 'react'; import { BrowserRouter as Router, Route, Redirect } from 'react-router-dom'; import { IonPage, IonRouterOutlet } from '@ionic/react'; import Home from './pages/Home'; /* Core CSS required for Ionic components to work properly */ import "@ionic/core/css/core.css"; /* Basic CSS for apps built with Ionic */ import "@ionic/core/css/normalize.css"; import "@ionic/core/css/structure.css"; import "@ionic/core/css/typography.css"; /* Optional CSS utils that can be commented out */ import "@ionic/core/css/padding.css"; import "@ionic/core/css/float-elements.css"; import "@ionic/core/css/text-alignment.css"; import "@ionic/core/css/text-transformation.css"; import "@ionic/core/css/flex-utils.css"; import "@ionic/core/css/display.css"; const App: React.SFC = () => ( <Router> <Route exact path="/" render={() => <Redirect to="/home"/>} /> <div className="App"> <IonPage> <IonRouterOutlet> <Route path="/:tab(home)" component={Home} exact={true} /> </IonRouterOutlet> </IonPage> </div> </Router> ); export default App;Ionic CLIは何をしてるの?
Ionic本体のコンポーネントはWeb Componentsになっていますので、基本的にはWeb Componentsをnpmで呼び出してきて利用する形です。ただ、ナビゲーションスタックや非線形ナビゲーションを実装するために、
React Router v4のRouterまわりを拡張しているので、そこあたりの設定など考えはじめると、自分でnpmでインストールして...みたいなことをするより、CLIを使ってはじめた方がお手軽かなという印象です。Ionic Reactはリリースされた?
現在、@ionic/reactのパッケージバージョン0.0.5でalpha版という位置づけです。
https://www.npmjs.com/package/@ionic/react
なので、CLIに導入されたといっても本リリースでないことにご注意ください。プロジェクト導入する際は
https://github.com/ionic-team/ionic/labels/package%3A%20react
あたりのIssuesをみながら検討いただければと思います。
それでは、また。
- 投稿日:2019-05-30T05:14:01+09:00
ReactやVueなどのJavascriptフレームワークからRailsの多対多モデルに対して、関連付けも含めて一気に作ってみた
こんにちは!@hairgaiです。
突然ですが、とあるTeamを作成するときにMemberを一緒に所属させたい!と思うことって一日に一回くらいありませんか?
今回は、それを実装するときにJavascriptからRailsへのパラメータで若干悩んだので、それを共有しようかなと思います。前提
よくある多対多です。
- Teamモデル
has_many :team_membershas_many :members, through: :team_members- TeamMemberモデル
belongs_to :teambelongs_to :member- Memberモデル
has_many :team_members: :destroyhas_many :teams, through: :team_membersReact 16.8.6、Rails 5.2.2
実装
Memberが数人いて何かTeamを作るときに、一度作成して後から所属させるのは面倒なので、当然ながら「Teamを作るときにMemberを所属させつつ作れたらいいのに」と思うと思います。
なので、フロントでTeamを作成するときに、既に登録済みのMemberを一覧で表示して、それを選択させることでパラメータを同時に送らせることにします。こんな感じですね。
また、Railsでは、モデルを作成するときに、その多対多関係にあるモデルを一緒に関連付けることが可能です。
なので、上記のように「Teamを作るときにMemberを所属させつつ作れたらいいのに」と思ったら、pry(main)> Member.create!(email: 'a@example.com') => #<Member:0x00007fb1498f04d8 id: 1, email: "a@example.com", # ... pry(main)> team = Team.create!(name: 'hoge', member_ids: [1]) => #<Team:0x00007fb142722860 id: 1, name: "hoge", # ... pry(main)> team.members => [#<Member:0x00007fb149951af8 id: 1, email: "a@example.com", # ... ]のように、
[モデル名]_idsというパラメータに配列を渡すと関連付けることが出来ます。
なので、フロント側でこのパラメータが渡ってくるようにURLパラメータを生成すれば良いということですね。パラメータ送りたい
ググると色々な記事が出てくる通り、JavascriptからURLにパラメータ用のクエリを乗っけるときは、qsを使いました。
qsは、Javascriptの連想配列(Hash)からURLパラメータを生成してくれるライブラリで、例えばimport qs from 'qs'; // or var qs = require('qs'); const params = { team: { name: 'hoge' }}; qs.stringify(params) // => 'team%5Bname%5D=hoge'という感じで使います。
なので(今回はパラメータの話なので解説しませんが)、フロント側でいい感じにパラメータを連想配列として生成します。// 実際はフレームワーク上でユーザの入力に合わせて作りますが、下記のような連想配列が生成されます。 const params = { team: { name: 'hoge', member_ids: [2, 3] } } qs.stringify(params) // => 'team%5Bname%5D=hoge&team%5Bmember_ids%5D%5B0%5D=2&team%5Bmember_ids%5D%5B1%5D=3'これをライブラリ等を用いてRailsに送ってみると…(axiosを使いました)
15: def update 16: binding.pry => 17: @team.update!(team_params) # ... [1] pry(#<Api::V1::TeamsController>)> params => <ActionController::Parameters {"team"=>{"id"=>"1", "name"=>"hoge", "member_ids"=>{"0"=>"1", "1"=>"2", "2"=>"3"}}, "format"=>"json", "controller"=>"api/v1/teams", "action"=>"update", "id"=>"1"} permitted: false>あれ?なんか変な形で送られてますね。
クエリの生成方法のオプションがあった
qsが生成したURLパラメータをデコードしてみると…team[name]=hoge&team[member_ids][0]=2&team[member_ids][1]=3ということで、
team[member_ids][0]=2&team[member_ids][1]=3のように指定されています。これをRailsでは"member_ids"=>{"0"=>"2", "1"=>"3"}と解釈してしまうようですね。(確かにHashっぽいです)
では、Railsではどう記述すればArrayと解釈されるのか、ということで、逆にArrayからクエリを生成してみましょう。pry(main)> { name: 'hoge', member_ids: [2, 3] }.to_query('team') => "team%5Bmember_ids%5D%5B%5D=2&team%5Bmember_ids%5D%5B%5D=3&team%5Bname%5D=hoge" # => team[member_ids][]=2&team[member_ids][]=3&team[name]=hoge順番は違いますが、若干指定の仕方が違いますね。Arrayのクエリでは、
[]のように数字を入れずに指定すれば良いようです。
現在はその数字の処理はqs側にまかせています。qsのGitHubをよく読んでみると…You may use the arrayFormat option to specify the format of the output array:
qs.stringify({ a: ['b', 'c'] }, { arrayFormat: 'indices' }) // 'a[0]=b&a[1]=c' qs.stringify({ a: ['b', 'c'] }, { arrayFormat: 'brackets' }) // 'a[]=b&a[]=c' qs.stringify({ a: ['b', 'c'] }, { arrayFormat: 'repeat' }) // 'a=b&a=c' qs.stringify({ a: ['b', 'c'] }, { arrayFormat: 'comma' }) // 'a=b,c'とのことです。
なので、フロント側でURLパラメータを生成する際に、const params = { team: { name: 'hoge', member_ids: [2, 3] } } qs.stringify(params, { arrayFormat: 'brackets' }) // => 'team%5Bname%5D=hoge&team%5Bmember_ids%5D%5B%5D=2&team%5Bmember_ids%5D%5B%5D=3'とオプションを追加してみると…
[1] pry(#<Api::V1::TeamsController>)> params => <ActionController::Parameters {"team"=>{"id"=>"1", "name"=>"hoge", "member_ids"=>["2", "3"]}, "format"=>"json", "controller"=>"api/v1/teams", "action"=>"update", "id"=>"1"} permitted: false>出来ました!レコードも正常に作られます。
結論
Railsは、Railsが提供するWayに沿えば非常に強力なフレームワークですが、その分色々な決まりがあるので、こういった細かいところもキチンと調べていきたいですね。
この記事が誰かの参考になれば幸いです。
参考
ありがとうございました!
- 投稿日:2019-05-30T00:57:41+09:00
2019年に知っておくべきJava ScriptのフレームワークTOP5
こんにちは、ベイマックスのでかい人形を買おうかどうか迷って半年になるテノヒラです
最近チームでwikiを書く文化が芽生えつつあるんですよ。
わたしもビギナーに向けてトレンドとかをお伝えするものがかければと思って記事を漁っていたら、フレームワークについてこじんまりかついい感じにまとめてある素晴らしい記事を発見したので翻訳してご紹介します!
翻訳する記事はこちら?
Top Javascript frameworks you should know in 2019
世界のトレンドと日本のトレンドはちょっと違ったりするので要チェックですところどころ意訳をしていますが、もし致命的な翻訳ミスがありましたら編集リクエストしてください
はじめに
JavaScriptは世界で一番人気のあるプログラミング言語です。
インターネットでほぼ全てのwebサイトのフォームに使われています。
JavaScriptまたはJavaScriptのフレームワーク、ライブラリ関係なくどこでもJavaScriptを見つけることができます。JavaScriptはフロントエンドだけでなくサーバーサイドの言語として使われています。
いまではJavaScriptでwebサイトを完全に構築させることができるのです下記が2019年で最も人気なフレームワーク5選です。
1) Angular
2) React
3) NodeJS
4) Vue.js
5) Backbone.js
Angular
Angularは最も人気のあるJavaScriptのフレームワークで、Typescriptのオープンソースです。
最初は2016年9月14日にGoogleがリリースしました。
AngularはMVC (Model-View-Conrtoller)パターンをベースにしています。
これは完璧なフレームワークで、企業のwebアプリケーションを構築するすべてを提供しています。
なのでAngularはwebアプリケーションを構築する上で最も人気のあるJavaScriptなのです。
大企業では大抵採用されています。React
Reactはユーザーインターフェイスを創るためのオープンソースのライブラリです。
2013年にFacebookによって開発されました。
Reactはコンポーネントベースで拡張性があり、webインターフェースを構築するのに速いフレームワークです。
Angularと異なっている部分は、Reactはwebインターフェースを構築する機能を提供しています。最近はReactがwebインターフェースを構築する最も人気があるJavaScriptライブラリのひとつとなりました。
ただ、Reactは最も手のかかるJavaScriptのライブラリです。
需要高いのでやれるようになれば思わず笑みが溢れるよう給与がもらえますNode JS
Nodejs、Node.jsもしくはNodeはオープンソースで、Google ChromeのJavaScript V8 Engineに基づいたサーバーサイドのJavaScriptのフレームワークです。
主に速い構築、拡張性、サーバーサイドアプリケーションをベースとした信頼性の高いネットワークを主に設計しています。
Indeed.comには現在、8,905つの求人があります。
Node開発者の平均的な給与はだいたい 10万5千ドル(約1,148万円)です。Vue.js
Vueもしくはvue.jsはユーザーインターフェースを構築するための革新的なフレームワークです。
ライブラリのコアは、表示のレイヤーだけに焦点を合わせている、簡単に習得できる、他のライブラリもしくは既存のプロジェクトとの統合といった部分です。
違う視点からみると、Vueはモダンなツールとサポートしているライブラリとを一緒に使った時に洗礼されたシングルページアプリケーションにすることができます。
webページの表示に焦点を当てたVueもフロントエンド界隈では人気のあるフレームワークとなります。Indeed.comには現在、1,316つの求人があります。
平均的な給与はおよそ10万ドル(約1,093万円)もしくはそれ以上です。Backbone.js
BackboneもしくはBackbone.jsはRESTful JSONインターフェースのフレームワークで、model–view–presenter (MVP)アプリケーションデザインパターンをベースとしているものです。
Backboneは2010年にJeremy Ashkenasによってつくられ、7年後には最も人気のあるフレームワークのひとつとなりました。
Indeed.comには現在、5,135つの求人があります。
backboneフロントエンドとbackboneフルスタックエンジニアの平均的な給与はそれぞれおよそ10万2千ドル(約1,115万円)と10万1千ドル(約1,104万円)です。React Vs Angular
ReactとAngularはweb開発者によって最も討論されることです。
これらを学習したプログラマーと開発者にとってどちらを学ぶべきなのかは悩むところです。
webサイトを開発する人にとってはどちらを使うべきかを悩みます。
どちらを採用するかを決定するのはいつも課題となります。Angularは完全なweb applicationの構築する機能を提供しており、Reactはインターフェースだけを構築するのに使われているライブラリです。
アーキテクチャーの概念によると、Angularはモデルと表示、制御の機能を処理しますが、Reactは表示のみを処理します。
AngularはTypescriptをベースとしていますが、ReactはJavascript上で動きます。
ReactはFacebookによって開発されましたが、AngularはGoogleによって開発されています。
AngularのIonicはモバイルアプリケーションの構築に使われますが、
Reactはモバイルアプリケーション開発のためにReact Nativeを提供します。
- 投稿日:2019-05-30T00:33:07+09:00
『React』 +『Redux』 + 『Firebase』でLINEのChat機能を作ろう! 【準備編】
はじめに
前回の記事では『電卓』の実装をしました。
その後以下の面白い記事と動画を見つけたので、早速参考にしてLINEのChat機能の一部分を実装してみました!一気に全部書くとすごく長くなりそうなので【準備編】、【Component編】、【状態管理編】の3部構成にして記事を書きたいと思います。今回は【準備編】です!
前回の記事
『React』+『Redux』でiPhoneに入ってるような電卓を作ってみよう!次回の記事
『React』 +『Redux』 + 『Firebase』でLINEのChat機能を作ろう! 【Component編】完成品
PigTalkから実際にアクセスできます!
準備編
恒例のcreate-react-app
terminalで以下のコマンドを入力しましょう!
$ create-react-app chat $ cd chat $ yarn startはい!これでReactを用いてアプリケーションを作る準備ができました!
create-react-appがわからない人はこちらの記事へ必要なパッケージのインストール
今回必要なパッケージは
- redux
- react-redux
- @material-ui/core
- @material-ui/icons
- firebase
です。
Material-UIはマテリアルデザインをReactアプリケーションに導入することができるUIコンポーネントです。Material-UIを使うことで、手軽にGoogleのマテリアルデザインを踏襲したアプリケーションを作ることができます。
早速インストールしましょう!
yarn add redux react-redux @material-ui/core @material-ui/icons firebaseFirebase
Firebaseとは、すばやく高品質のモバイルアプリを開発することができるプラットフォームで、開発に役立つ数多くの機能が用意されています。今回は『Hosting』と『Realtime Database』を使用しました!
気になる使い方
https://firebase.google.com/?hl=jaにアクセスしGoogleのアカウントでログインしコンソール画面に移動します。
プロジェクトの追加を押して、自分の好きなプロジェクト名を入力しましょう!
ウェブアプリを追加するために、アプリに好きなニックネームを入力します。
これでSDKが入手できます。
Firebase Realtime Databaseとの紐付け
firebase/config.jsを作成し、Firebaseとの接続情報を記載します。src/firebase/config.jsexport const firebaseConfig = { apiKey: "****************", authDomain: "****************", databaseURL: "****************", projectId: "****************", appId: "****************", storageBucket: "****************", messagingSenderId: "****************" };
firebase/index.jsでデータベース参照用のインスタンスを作成します。
このファイルをインポートすることで、どこからでもデータベースにアクセスすることができます。src/firebase/index.jsimport firebase from 'firebase'; import {firebaseConfig} from './config.js'; export const firebaseApp = firebase.initializeApp(firebaseConfig); export const firebaseDb = firebaseApp.database();これにて準備完了です!
次回は
『Material-ui』を使ってComponentを作成し、アプリケーションの見た目を整えていきます!
リファレンス
- 投稿日:2019-05-30T00:33:07+09:00
『React』 +『Redux』 + 『Firebase』でLINE風のChat機能を作ろう! 【準備編】
はじめに
前回の記事では『電卓』の実装をしました。
その後以下の面白い記事と動画を見つけたので、早速参考にしてLINE風のChat機能の一部分を実装してみました!一気に全部書くとすごく長くなりそうなので【準備編】、【Component編】、【状態管理編】の3部構成にして記事を書きたいと思います。今回は【準備編】です!
前回の記事
『React』+『Redux』でiPhoneに入ってるような電卓を作ってみよう!次回の記事
『React』 +『Redux』 + 『Firebase』でLINE風のChat機能を作ろう! 【Component編】完成品
PigTalkから実際にアクセスできます!
準備編
恒例のcreate-react-app
terminalで以下のコマンドを入力しましょう!
$ create-react-app chat $ cd chat $ yarn startはい!これでReactを用いてアプリケーションを作る準備ができました!
create-react-appがわからない人はこちらの記事へ必要なパッケージのインストール
今回必要なパッケージは
- redux
- react-redux
- @material-ui/core
- @material-ui/icons
- firebase
です。
Material-UIはマテリアルデザインをReactアプリケーションに導入することができるUIコンポーネントです。Material-UIを使うことで、手軽にGoogleのマテリアルデザインを踏襲したアプリケーションを作ることができます。
早速インストールしましょう!
yarn add redux react-redux @material-ui/core @material-ui/icons firebaseFirebase
Firebaseとは、すばやく高品質のモバイルアプリを開発することができるプラットフォームで、開発に役立つ数多くの機能が用意されています。今回は『Hosting』と『Realtime Database』を使用しました!
気になる使い方
https://firebase.google.com/?hl=jaにアクセスしGoogleのアカウントでログインしコンソール画面に移動します。
プロジェクトの追加を押して、自分の好きなプロジェクト名を入力しましょう!
ウェブアプリを追加するために、アプリに好きなニックネームを入力します。
これでSDKが入手できます。
Firebase Realtime Databaseとの紐付け
firebase/config.jsを作成し、Firebaseとの接続情報を記載します。src/firebase/config.jsexport const firebaseConfig = { apiKey: "****************", authDomain: "****************", databaseURL: "****************", projectId: "****************", appId: "****************", storageBucket: "****************", messagingSenderId: "****************" };
firebase/index.jsでデータベース参照用のインスタンスを作成します。
このファイルをインポートすることで、どこからでもデータベースにアクセスすることができます。src/firebase/index.jsimport firebase from 'firebase'; import {firebaseConfig} from './config.js'; export const firebaseApp = firebase.initializeApp(firebaseConfig); export const firebaseDb = firebaseApp.database();これにて準備完了です!
次回は
『Material-ui』を使ってComponentを作成し、アプリケーションの見た目を整えていきます!
リファレンス















