react+reduxを使ってカウンタ機能を実現し、問題が発生しました。


Reduxは、それ自体が単純な状態管理者であり、その歴史を遡らずに、グローバルのオブジェクトstoreを提供し、storeは、すべてのアプリケーションデータを含むstateオブジェクトを含み、storeはいくつかのreducer方法を提供しています。これらの方法はカスタマイズでき、使用者はstateの値を変えることができる。stateの値は読み取り専用であり、変更が必要な場合はreducerを通過するしかない。
Redux
  • コアオブジェクト:store
  • データストア:state
  • 状態更新提出インターフェース:==dispatch==
  • 状態更新提出パラメータ:typeとpayloadの==アクション==
  • 状態更新計算:==reducer==
  • 制限:reducerは純粋な関数でなければなりません。非同期
  • はサポートされていません。
  • 特性:ミドルウェア
  • をサポートします。
    React+Redux
    recatでreduxを使わない時に発生した問題
    reactでコンポーネント通信のデータは一方向で、トップのコンポーネントはprops属性を通じて下のコンポーネントにデータを転送することができますが、下部のコンポーネントは上のコンポーネントにデータを転送することができません。下のコンポーネントにデータを修正するためには、上のグループから下のグループにデータを転送する方法が必要です。プロジェクトがますます進むと、コンポーネント間でデータの転送が難しくなります。

    reactにreduxを加えるメリット
    reduxを使ってデータを管理し、Storeはコンポーネントと独立しているため、データ管理がコンポーネントと独立して、コンポーネント間のデータ転送が困難な問題を解決しました。

    reduxを使う
    ダウンロード
    
    npm install redux react-redux
    仕事の流れ
  • コンポーネントは、dispatchによってaction
  • をトリガする。
  • storeはactionを受け取り、actionをreducer
  • に配信する。
  • reducerは、actionタイプに従って状態を変更し、変更したデータをstore
  • に戻す。
  • コンポーネントは、storeの状態を購読しています。storeの状態更新は、コンポーネント
  • に同期されます。

    react+reduxを使ってカウンタを実現します。
    1.プロジェクトを作成し、reduxをインストールする
    
    #       react            reate   
    npm install -g create-react-app
    #   reate  
    create-react-app    
    #     
    cd    
    #    redux
    npm install redux reate-redux
    2.reduxを導入し、最初に実現したコードに基づいてreactでカウンタを実現する。
    
    //index.js
    import React from 'react';
    import ReactDOM from 'react-dom';
    import App from './App';
    import { createStore } from 'redux';
    
    const initialState = {
      count: 0
    }
    function reducer(state = initialState, action) {
      switch (action.type) {
        case 'increment':
          return {
            count: state.count + 1
          }
        case 'decrement':
          return {
            count: state.count - 1
          }
    
        default:
          return state
      }
    }
    const store = createStore(reducer)
    
    const increment = {
      type: 'increment'
    }
    
    const decrement = {
      type: 'decrement'
    }
    
    function Count() {
      return <div>
        <button onClick={() => store.dispatch(increment)}>+</button>
        <span>{store.getState().count}</span>
        <button onClick={() => store.dispatch(decrement)}>-</button>
      </div>
    }
    
    store.subscribe( () => {
      console.log(store.getState())
      ReactDOM.render(
        <React.StrictMode>
          <Count />
        </React.StrictMode>,
        document.getElementById('root')
      );
    })
    
    ReactDOM.render(
      <React.StrictMode>
        <Count />
      </React.StrictMode>,
      document.getElementById('root')
    );
    明らかに以上のようにカウンタの機能を実現することができますが、実際のプロジェクトでは必ずこのように使用することができません。コンポーネントは一般的に個別のファイルの中にあります。このような方式は他のコンポーネントでは明らかにStoreを取得できません。
    カウンタケースコード最適化-storeグローバルにアクセスできるようにする
    Store取得問題を解決するためにreact-reduxを使ってこの問題を解決する必要があります。react-reduxはProviderコンポーネントとconnect方法を提供してくれます。
    Provideコンポーネント
    一つのコンポーネントができますよね。作成したstoreはグローバルなところに置いて、コンポーネントをstoreに持ってきて、providerのコンポーネントを通して、storeをグローバルなコンポーネントの届くところに置いて、providerは私達に一番外側のコンポーネントに置くように要求します。
    プロジェクト
    connectは私達にstoreの状態を購読するように助けてくれます。状態が変わったらコンポーネントを再レンダリングしてください。
    connect方法によって、私達はstoreの状態を手に入れて、storeの状態をpropsにマッピングすることができます。
    connect方法によってdispatch方法を得ることができます。
    connectのパラメータは関数です。この関数はstoreの状態を得ることができます。この関数はオブジェクトを返す必要があります。このオブジェクトに書いた内容はコンポーネントのprops属性にマッピングされます。
    connectが呼び出した後、関数に戻って戻ってきたこの関数は、引き続き呼び出しを行うために、そのコンポーネントにマッピングするpropsが必要であることを知らせるために、着信コンポーネントが必要です。
    Componentフォルダの新規作成、Count.jsファイルの作成
    
    import React from 'react'
    
    function Count() {
        return <div>
            <button onClick={() => store.dispatch(increment)}>+</button>
            <span>{store.getState().count}</span>
            <button onClick={() => store.dispatch(decrement)}>-</button>
        </div>
    }
    
    export default Count
    Providerモジュールを導入して最外階に置いて、storeを作成します。
    
    ReactDOM.render(
      //   provider     store                   provider           
      <Provider store={store}><Count /></Provider>,
      document.getElementById('root')
    );
    connectメソッドを導入してconnectの使用によってコンポーネントを包む。
    
    const mapStateProps = state => ({
        count: state.count,
        a: '1'
    })
    // connect                  store    ,                ,                  props  
    // connect                              connect          props
    export default connect(mapStateProps)(Count)
    Countコンポーネントを改造してactionをこのファイルにコピーします。
    
    const increment = {
        type: 'increment'
    }
    
    const decrement = {
        type: 'decrement'
    }
    function Count({count,dispatch}) {
        return <div>
            <button onClick={() => {dispatch(increment)}}>+</button>
            <span>{count}</span>
            <button onClick={() => {dispatch(decrement)}}>-</button>
        </div>
    }
    現在のプロジェクトはもう実行できますが、Countコンポーネントの中のActionを提出する長いシリアルコードはビューの読み取り可能性に影響を与えますので、コードの最適化が必要です。
    カウンタケースコードの最適化-ビューのコードの読み取り可能性を高める
    私たちはビューで直接関数を呼び出したいです。このようにビューコードの読み取り可能性が高いです。これはconnectの第二のパラメータを利用する必要があります。第二のパラメータは関数です。この関数のイメージはdispatch方法です。この関数がオブジェクトに戻るように要求します。このオブジェクトの内容はコンポーネントのprops属性にマッピングされます。
    一つの変数がconnectの中の第二のパラメータであることを明らかにし、この変数の中で異なるaction操作を行う対象を返します。
    
    // connect                          dispatch                            props 
    const mapDispatchToProps = dispatch => ({
        increment (){
            dispatch({
                type: 'increment'
            })
        },
        decrement (){
            dispatch({
                type: 'decrement'
            })
        }
    })
    
    // connect                  store    ,                ,                  props  
    // connect                              connect          props
    export default connect(mapStateProps, mapDispatchToProps)(Count)
    コンポーネント中の構造propsはビューで直接的にイベントをバインディングする。
    
    function Count({count,increment,decrement}) {
        return <div>
            <button onClick={increment}>+</button>
            <span>{count}</span>
            <button onClick={decrement}>-</button>
        </div>
    }
    今回の最適化によって、dispatchを起動してactionを起動する方法のコードは重複していることが分かりました。
    dispatch起動actionを最適化する方法の重複コードの簡略化
    ビッドアクションクリエーターを利用して、dispatchトリガactionの動作を簡略化して、bitアクションクリエーターを助けてくれます。
    bindActioCreatorsには二つのパラメータがあります。一つ目のパラメータはactionを実行する対象で、二つ目のパラメータはdispach方法です。
    action操作を分離して、store/actions/counter.actions.jsファイルを新規作成してaction操作を実行することをこのファイルに単独に置いてエクスポートします。
    
    export const increment = () => ({type: 'increment'})
    export const decrement = () => ({type: 'decrement'})
    Count.jsにカウンタに関するactionを導入し、bindActioCreators方式でdispatchを生成してaction関数を実行する。
    
    import { bindActionCreators } from 'redux'
    import * as counterActions from './../store/actions/counter.actions'
    
    
    const mapDispatchToProps = dispatch => (bindActionCreators(counterActions, dispatch))
    // connect                  store    ,                ,                  props  
    // connect                              connect          props
    export default connect(mapStateProps, mapDispatchToProps)(Count)
    コードの最適化はここまで来ました。reduxのコードはコンポーネントと融合しています。だから私は独立したものに分解したいです。なぜreduxから引き離すべきですか?コード構造をもっと合理的にしたいからです。
    カウンターを再構築し、redux関連コードを引き抜きます。
    reducer関数を別のファイルに引き出して、作成storeを別のファイルに引き出します。
    reducerとactionsには文字列を書いていますが、文字列にはヒントがありませんので、文字列を定数として定義します。単語の間違いを防ぐという低級なエラーが発生します。src/store/const/counter.co nst.jsファイルを新規作成します。
    
    export const INCREMENT = 'increment'
    export const DECREMENT = 'decrement'
    新しいsrc/store/reducers/counter.reducers.jsファイルはreducer関数をこのファイルの中から引き出します。
    
    import { INCREMENT, DECREMENT} from './../const/counter.const'
    const initialState = {
        count: 0
    }
    // eslint-disable-next-line import/no-anonymous-default-export
    export default (state = initialState, action) => {
        switch (action.type) {
            case INCREMENT:
                return {
                    count: state.count + 1
                }
            case DECREMENT:
                return {
                    count: state.count - 1
                }
    
            default:
                return state
        }
    }
    actionsの文字列を導入変数に変更します。
    
    import { INCREMENT, DECREMENT} from './../const/counter.const'
    
    export const increment = () => ({type: INCREMENT})
    export const decrement = () => ({type: DECREMENT})
    src/store/index.jsファイルを作成し、このファイルにstoreを作成してエクスポートします。
    
    import { createStore } from 'redux';
    import reducer from './reducers/counter.reducers'
    
    export const store = createStore(reducer)
    storeを導入したファイルで沖プロジェクトのstoreファイルに変更してstoreを導入します。
    
    import React from 'react';
    import ReactDOM from 'react-dom';
    import Count from './components/Count';
    import { store } from './store'
    import { Provider } from 'react-redux'
    /**
     * react-redux  react   redux     
    *    Provider               store                  store
    *    connect       
     */
    
    
    ReactDOM.render(
      //   provider     store                   provider           
      <Provider store={store}><Count /></Provider>,
      document.getElementById('root')
    );
    
    actionのためにパラメータを伝達し、カウンタケースを拡張します。
    このカウンターケースはもうボタンを押して一つ減らして操作しました。今は新しい需要があります。例えば5をプラスして5を減らす必要があります。
    これはactionにパラメータを伝える必要があります。
    ビューでボタンバインディング関数がパラメータに入ります。
    
    function Count({count,increment,decrement}) {
        return <div>
            <button onClick={() => increment(5)}>+</button>
            <span>{count}</span>
            <button onClick={() => decrement(5)}>-</button>
        </div>
    }
    dispacthがaction動作を行うときにパラメータを受け取り、actionに入ります。
    
    export const increment = payload => ({type: INCREMENT, payload})
    export const decrement = payload => ({type: DECREMENT, payload})
    reducersでパラメータを受信し、対応する処理を行う。
    
    export default (state = initialState, action) => {
        switch (action.type) {
            case INCREMENT:
                return {
                    count: state.count + action.payload
                }
            case DECREMENT:
                return {
                    count: state.count - action.payload
                }
    
            default:
                return state
        }
    }
    原文の住所:https://kspf.xyz/archives/10/
    以上、reactでreduxを使ってカウンタケースを実現する記事について紹介しました。これまでの記事を検索したり、次の関連記事を見たりしてください。これからもよろしくお願いします。