Redux Toolkit非公式翻訳(2) Basic Tutorial

元ページ: redux-toolkit.js.org


基本的なチュートリアル

Redux Toolkitへようこそ!これはRedux Toolkitに含まれる基本的な関数を紹介するチュートリアルです。

このチュートリアルでは、読者は既にReduxそのものや、Reactと組み合わせて使う方法についてはよく知っているものと仮定しています。もしあなたがそうでないなら、まずはReduxやReactのドキュメントに目を通してみて下さい。ここではRedux Toolkitの使用法がどのように"典型的"なReduxのコードと異なるのかを中心に説明していきます。

イントロダクション:カウンターアプリケーションを作る

まずは、とても小さなReduxのサンプルを見てみることから始めましょう。シンプルなカウンターのアプリケーションです。

Reduxによるカウンターアプリの例

Reduxのドキュメントには"バニラ"なカウンターアプリのサンプルがあります。このサンプルは、一つの数値を持ち、"INCREMENT"や"DECREMENT"のようなaction typeに応じて動作するRedux storeとreducerの作成方法が示されています。完全なコードはCodesandboxで確認することができますが、簡略化したコードは下にあります。

function counter(state, action) {
  if (typeof state === 'undefined') {
    return 0
  }
  
  switch (action.type) {
    case 'INCREMENT':
      return state + 1
    case 'DECREMENT':
      return state - 1
    default:
      return state
  }
}

var store = Redux.createStore(counter)

document.getElementById('increment').addEventListener('click', function () {
  store.dispatch({ type: 'INCREMENT' })
})

このコードではcounterというreducer関数を作成しています。この関数はデフォルトのstate値として0を取り、"INCREMENT"と"DECREMENT"というaction typeを受け取り、ボタンがクリックされたときaction typeの"INCREMENT"をdispatchします。

例を修正する

上記の例はシンプルですが、あまり現実的ではありません。ほとんどのReduxアプリはES6記法で書かれているし、関数はundefinedなパラメータが渡ってきた場合のためにデフォルト引数を含んでいるものです。また、コードに直接actionオブジェクトを記述するのではなく"action creator"関数を定義し、action typeを毎回記述するのではなく定数として定義しておくほうが一般的です。

上記のアプローチを使って最初の例を修正してみましょう。

const INCREMENT = 'INCREMENT'
const DECREMENT = 'DECREMENT'

function increment() {
  return { type: INCREMENT }
}

function decrement() {
  return { type DECREMENT }
}

function Counter(state = 0, action) {
  switch(action.type) {
    case INCREMENT:
      return state + 1
    case DECREMENT:
      return state - 1
    default:
      retunr state
  }
}

const store = Redux.createStore(counter)

document.getElementById('increment').addEventListener('click', () => {
  store.dispatch(increment())
})

この例は小さなものなので、あまり見た目に大きな変化はないでしょう。サイズに関しては、デフォルト引数を使うことで数行削減できましたが、action creator関数を追加したことでさらに大きくなっています。そして重複している箇所があります。
const INCREMENT = 'INCREMENT'はばかげているように見えるでしょう:) 特に、これに関しては二カ所でしか使われていません。action creatorとreducerです。

加えて、switch式は多くの人にとってはわずらわしいものです。代わりにこれをlookup tableのようなものに置き換えることができれば良さそうです。

configureStore

Redux ToolkitにはReduxコードをシンプルにするいくつかの関数が含まれています。最初の関数はconfigureStoreです。

通常は、createStore()を呼び出してルートreducer関数を渡すことでRedux storeを作成します。Redux Toolkitでは、createStorre()をラップしたconfigureStore()を使うことで同じことができます。

既存のcreateStore呼び出しは簡単にconfigueStoreに置き換えられます。configureStoreは複数の引数でなく名前付きフィールドが定義された単一のオブジェクトを受け取るため、reducer関数をreducerフィールドとして渡す必要があります。

// 変更前
const store = createStore(counter)

// 変更後
const store = configureStore({
  reducer: counter
})

変更前と比べてあまり違いが無いように見えます。しかし実際には、dispatchされたactionやsttateの変更が確認できるようstoreはRedux DevToolsExtensionが使えるような形で定義され、いくつかのミドルウェアが自動で含まれます。詳細は次のチュートリアルで確認しましょう。

createAction

次はcreateActionを見てみましょう。

createActionはaction typeの文字列を引数として受け取り、type文字列を使用するaction creator関数を返します。(これはつまり、この関数の名前が少し不正確だということです。関数は"actionオブジェクト"でなく"action creator関数"を作成します。しかしcreateActionCreatorよりは短くて覚えやすいのでこの名前になっています。)次の2つの例は同じ意味です。

// オリジナル:手動でaction typeとaction creatorを記述する
const INCREMENT = 'INCREMENT'

function incrementOriginal() {
  return { type: INCREMENT }
}

console.log(incrementOriginal())
// { type: "INCREMENT" }

// 'createAction'を使ってaction creatorを生成する
const incrementNew = createAction('INCREMENT')

console.log(incrementNew())
// { type: "INCREMENT" }

reducerの中でaction type文字列を参照する必要がある場合はどうでしょうか。createActionを使えば、2つのやり方で実現できます。1つ目はオーバーライドされたaction creatorのtoString()を使う方法です。このメソッドはaction type文字列を返します。2つ目は関数の.typeフィールドで取得する方法です。

const increment = createAction('INCREMENT')

console.log(increment.toString())
// "INCREMENT"

console.log(increment.type)
// "INCREMENT"

createActionによって前のカウンターアプリのサンプルをシンプルにできます。

const increment = createAction('INCREMENT')
const decrement = createAction('DECREMENT')

function counter(state = 0, action) {
  switch(action.type) {
    case increment.type:
      return state + 1
    case decrement.type;
      return state - 1
    default:
      return state
  }
}

const store = Redux.createStore(counter)

document.getElementById('increment').addEventListener('click', () => {
  store.dispatch(increment())
})

configureStoreの時のように数行削減できました。また、INCREMENTのような文字列が重複しているようなこともありません。

createReducer

reducer関数を見てみましょう。reducerではif式やループなどの条件付きロジックを扱うことができますが、最も一般的なアプローチはaction.typeフィールドをチェックしてaction typeに応じた処理を行うやり方です。reducerは初期値も提供し、actionがそのreducerが関心を持つものでなければ既存のstateを返します。

Redux ToolkitはcreateReducerという関数を含んでいます。これを使うことで、"lookup table"のようなオブジェクトを使ってreducerを記述することができます。このオブジェクトはそれぞれのキーがReduxのaction type文字列になっており、値はreducer関数です。これを使って直接既存のcountr関数を置き換えることができます。action type文字列をキーとして使う必要があるため、type文字列からキーを作成するためにES6オブジェクトの"computed property"シンタックスを使うことができます。

const increment = createAction('INCREMENT')
const decrement = createAction('DECREMENT')

const counter = createReducer(0, {
  [increment.type]: state => state + 1,
  [decrement.type]: state => state - 1
})

完全なコードを確認する場合はcreateActionとcreateReducerの使い方を示したCodeSandboxコードを見てください。

createSlice

この時点でcounterのサンプルコードがどんな風になっているか見てみましょう。

const increment = createAction('INCREMENT')
const decrement = createAction('DECREMENT')

const counter = createReducer(0, {
  [increment]: state => state + 1,
  [decrement]: state => state - 1
})

const store = configureStore({
  reducer: counter
})

document.getElementById('increment').addEventListener('click', () => {
  store.dispatch(increment())
})

悪くはないですが、もう一つ大きな変更を加えることができます。なぜaction creatorをばらばらに生成したり、action type文字列を書き出したりしないといけないのでしょうか?ここで本当に重要なのはreducer関数です。

createSlice関数はまさにこのためにあります。この関数によってreducer関数を含むオブジェクトを取得することができ、またユーザーが指定したreducerの名称に基づいて自動的にaction type文字列とaction creator関数を生成します。

createSliceは”slice”というオブジェクトを返します。これは生成されたreducer関数をreducerというフィールドに含み。actionsフィールドにaction creatorsがセットされています。

createSliceを使って書き換えたカウンターアプリの例はこちらです。

const counterSlice = createSlice({
  name: 'counter',
  initialState: 0,
  reducers: {
    increment: state => state + 1,
    decrement: state => state - 1
  }
})

const store = configureStore({
  reducer: counterSlice.reducer
})

document.getElementById('increment').addEventListener('click', () => {
  store.dispatch(counterSlice.actions.increment())
})

多くの場合、ES6の分割記法を使ってaction creatorやreducerを変数として読み込みたいと思います。

const { actions, reducer } = counterSlice
const { increment, decrement } = actions

まとめ

それぞれの関数の機能についてまとめてみましょう。

  • configureStore: Redux独自のcreateStoreのようにRedux storeインスタンスを作成しますが、こちらは名前付きオプションがセットされたオブジェクトを受け取り、Redux DevTools拡張を自動的にセットアップします。
  • createAction: action type文字列を受け取り、その文字列を使用するaction creator関数を返します。
  • createReducer: stateの初期値とreducer関数に対応するaction typeのリストを受け取り、全てのaction typeを制御するreducerを生成します。
  • createSlice: state初期値、reducer名と対応する関数のリストを受け取り、action creator関数、action type文字列、reducer関数を自動で生成します。

これらの関数はReduxの挙動自体を変えるものではないことに注意してください。私たちは未だにRedux storeを作成し、どの処理を実行するかが記載されたactionオブジェクトをdispatchし、reducer関数を使って更新されたstateを返しています(注:オリジナルのReduxを使う場合とRedux-Toolkitの上記関数群を使う場合では、どちらも行っている処理の流れ自体は同じ)。

また、Redux Toolkitの関数群は、UIを構築する際にどんなアプローチを取ったとしても使うことができます。これは、各関数が単に"プレーンなRedux store"を扱うだけのものだからです。今回のサンプルではバニラなJSによってstoreを扱いましたが、同じことはReactやAngular、VueなどUI層に何を採用したとしても同じように行うことができます。

最後に、サンプルをよく見てみると、非同期な処理を行っている箇所が一つあるのがわかると思います。"increment async"ボタンです。

document.getElementById('incrementAsync').addEventListener('click', function() {
  setTimeout(function() {
    store.dispatch(incremenet())
  }, 1000)
})

非同期処理をreducerのロジックから切り離し、storeを更新する必要があるときにactionをdispatchしているのがわかると思います。Redux Toolkitはこの点については何も変更しません。

サンプルの完全なコードは以下です。

<!DOCTYPE html>
<html>
  <head>
    <title>Redux Starter Kit: createSlice Example</title>
    <script src="https://unpkg.com/@reduxjs/toolkit@latest/dist/redux-toolkit.umd.js"></script>
  </head>
  <body>
    <div>
      <p>
        Clicked: <span id="value">0</span> times
        <button id="increment">+</button>
        <button id="decrement">-</button>
        <button id="incrementIfOdd">Increment if odd</button>
        <button id="incrementAsync">Increment async</button>
      </p>
    </div>
    <script>
      const RTK = window.RTK;

      const counterSlice = RTK.createSlice({
        name: "counter",
        initialState: 0,
        reducers: {
          increment: state => state + 1,
          decrement: state => state - 1
        }
      });

      const { increment, decrement } = counterSlice.actions;

      const store = RTK.configureStore({ reducer: counterSlice.reducer });
      const valueEl = document.getElementById("value");

      function render() {
        valueEl.innerHTML = store.getState().toString();
      }

      render();
      store.subscribe(render);

      document
        .getElementById("increment")
        .addEventListener("click", function() {
          store.dispatch(increment());
        });

      document
        .getElementById("decrement")
        .addEventListener("click", function() {
          store.dispatch(decrement());
        });

      document
        .getElementById("incrementIfOdd")
        .addEventListener("click", function() {
          if (store.getState() % 2 !== 0) {
            store.dispatch(increment());
          }
        });

      document
        .getElementById("incrementAsync")
        .addEventListener("click", function() {
          setTimeout(function() {
            store.dispatch(increment());
          }, 1000);
        });
    </script>
  </body>
</html>

それぞれの関数の基本が理解できたと思います。次のステップでは、関数の機能をさらに詳しく見るためにもう少し大規模なサンプルに組み込んでいきます。これは中級チュートリアルで行います。

Redux Toolkit非公式翻訳(1) QuickStart

Redux Toolkit私家版翻訳。
私の英語力は全然高くない(ちゃんと英語を訳したのは大学受験以来)ので、あまり正確な訳は期待しないでください。
元ページ: redux-toolkit.js.org


クイックスタート

目的

Redux ToolkitはReduxを記述する上での標準になることを意図して作られましたが、元々はReduxについての3つのよくある問題を解決するために作られました。

  • Redux storeの設定が複雑すぎる
  • Reduxを便利に使うためにはたくさんのパッケージを導入しないといけない
  • Reduxを使うにはたくさんのボイラープレートコードの記述が必要

全てのユースケースを解決することはできませんが、create-react-appや`apollo-boost のように、セットアップ手順を抽象化し、一般的なユースケースに対応し、アプリケーションのコードをシンプルにしてくれる便利なユーティリティを含むようなツールを提供することはできます。

これらの理由により、このパッケージはあえてスコープを限定しています。"Reduxモジュールを再利用可能でカプセル化されたものにする"といったようなコンセプトは考慮していませんし、データのキャッシュやフォルダ/ファイル構造、storeにおけるエンティティのリレーションなどといったものにも対応していません。

つまり、全てのReduxユーザにとって有用である必要があります。最初のプロジェクトをセットアップしている初心者や、既存のアプリケーションをシンプルにしたいと思っている経験者などにかかわらず、このツールはあなたのReduxコードをより良いものにしてくれます。

このツールに含まれるもの

Redux Toolkitには以下のAPIが含まれます。

  • configureStore(): シンプルな設定オプションや標準を提供するためにcreateStoreをラップしています。自動的にslice reducerを組み合わせ、redux-thunkのようなミドルウェアをデフォルトで追加し、Redux DevToolsを利用可能にします。
  • createReducer(): 自分でswitch式を書かずに済むように、reducer関数を呼び出すためのaction typesのセットを提供します。さらに、通常のミュータブルなコード(こんなコードです:state.todos[3].completed = true)でシンプルにイミュータブルな更新を行えるよう自動的にimmerというライブラリを使用します。
  • createAction(): action creater関数を生成します。関数にはtoString()が定義されており、action typeを使用するような場所で呼ぶことができます。
  • createSlice(): reducer関数のオブジェクトやslice名、stateの初期値を受け取り、action createrやaction typesに対応するslice reducerを自動で生成します。
  • createAsyncThunk: action type文字悦とpromiseを返す関数を受け取り、promiseに基づいてpending/resolved/rejectedというaction typeを* dispatchするthunkを生成します。
  • createEntityAdapter: storeで正規化されたデータを扱うための再利用可能なreducerを生成します。
  • createSelector: Reselectライブラリから再exportされたユーティリティです。

インストール

Create React Appを使う

ReactとRedux Toolkitをを使ったアプリケーションを立ち上げる際は、Ceate React Appに用意された公式テンプレートを使用することを推奨しています。これにはReact ReduxをReactのコンポーネントに統合しやすいというメリットがあります。

npx create-react-app my-app --template redux

既存のアプリに導入する

Redux Toolkitはモジュールバンドラーを使ってnpmパッケージとして利用したり、Nodeアプリケーションで使うことができます。

# npm
npm install [eduxjs/toolkit

# yarn
yarn add @reduxjs/toolkit

また、グローバル変数window.RTKが定義されたプリコンパイル済みのUMDパッケージとして利用することもできます。UMDパッケージは<script>タグで直接使用することができます。

macにoracle 11g(sql*plus)を導入する

【環境】
mac book pro Sierra 10.12.1


職場はDBにoracleを使っている。自宅でも環境を合わせて勉強したいので手持ちのmacに導入することにした。


【概要】
vagrantoracle乗せたVM(ubuntu12.04)立ててmacローカルからsql*plusで接続


【手順】
1.vagrantをインストールする
↓このへん参照↓
qiita.com


2.githubより有志(神)が作成してくれたvagrantfileをclone
*任意のフォルダで実行

git clone https://github.com/hilverd/vagrant-ubuntu-oracle-xe.git


3.vagrantプラグインvgguestをインストール

vagrant plugin install vagrant-vbguest


4.oracle 11gをダウンロード
oracleのアカウントが必要 この後にも必要になるのでここでさくっと作っておく
Oracle Database Express Edition 11g Release 2 Downloads


5.落としてきたoracleクライアントをcloneしたvagrantfile配下のmodules/oracle/filesに格納する

6.おもむろにvagrantを立ち上げる
*2でcloneしたvagrantfileのフォルダ直下で実行
*初回は相当時間かかる。10〜20分くらい

vagrant up


7.sql*plusなど必要なクライアントをダウンロードする
Instant Client downloads for Mac OS X (Intel x86)
ここから以下の4つを落とす

  • instantclient-basic-macos.x64-11.2.0.4.0.zip
  • instantclient-jdbc-macos.x64-11.2.0.4.0.zip
  • instantclient-sqlplus-macos.x64-11.2.0.4.0.zip
  • instantclient-sdk-macos.x64-11.2.0.4.0.zip


8.適当な場所に上記の4つを解凍する
*最後にパス通すのでどこに置いてもok 1つのフォルダに中身全部まとめること
*筆者は以下のようにまとめました

unzip instantclient-basic-macos.x32-11.2.0.4.0.zip -d ~/lib/oracle/instantclient_11_2
unzip instantclient-jdbc-macos.x32-11.2.0.4.0.zip -d ~/lib/oracle/instantclient_11_2
unzip instantclient-sdk-macos.x32-11.2.0.4.0.zip -d ~/lib/oracle/instantclient_11_2
unzip instantclient-sqlplus-macos.x32-11.2.0.4.0.zip -d ~/lib/oracle/instantclient_11_2

9..bash_profileに追記してパスを通す

# .bash_profile
# 以下を追記

export ORACLE_HOME=~/lib/oracle/instantclient_11_2 # パスは自分がフォルダを置いた場所に読み替えること
export PATH=$ORACLE_HOME:$PATH
export DYLD_LIBRARY_PATH=~/lib/oracle/instantclient_11_2 # ここもパス読み替えて
export NLS_LANG=American_America.AL32UTF8
source .bash_profile


10.おもむろにsql*plusを立ち上げる

sqlplus system/manager@//localhost:1521/XE


おわり


【参考】
taiju.hatenablog.com
qiita.com
https://github.com/hilverd/vagrant-ubuntu-oracle-xe

PHP初心者がPHPBrewに手を出すべきでは無かった

PHPBrewを使えば色んなバージョンのPHPが簡単に共存させられると書いてあったから入れてみたら

 

apacheに読み込ませる→エラー

mysql使う(PDO)→エラー

mysqlのエラーを解消しようとしてる間にSymbol not foundとかいう謎のエラー

 

上の三つのエラー、ググってもほとんどまともな情報が無い。。。

 

macPHPをインストールする手順を調べると、いくつかのブログでPHPBrewが妙にオススメ感強めで出てくるけど

初心者が気軽に手を出すべきものではないのかもしれない。

素直にMAMP使おうと思いました。

PHP7をざっくり体験できるtutorialサイトがあった

こういうサイトがあった。

http://php7-tutorial.com/

 

PHPそのままのコードでは動かなくなるような変更点をトピックごとに紹介している。

変更点の簡単な説明と、それを具体的にあらわした、実際にPHP7で動かない「まずいコード」の例が挙げられている。

まずいコード例はそのまま編集できるようになっていて、説明通りにコードを修正すると次のトピックに進める。

 

PHP7の魅力を伝えるというより、既にPHPを使っている人向けにバージョンアップの注意しどころを教える感じ。

普段PHP触ってないので「へえ」って感じでした。