さまざまなReact状態マネージャーの解釈と使用方法

さまざまなReact状態マネージャーの解釈と使用方法

まず、状態マネージャーとは何か、そしてそれが何をするのかを知る必要があります。

複数のページで同じプロパティを使用する場合、状態マネージャーを使用してこれらの状態を別の外部ファイルに保存し、必要なときにいつでも簡単に取得できるようにすることができます。

React は Vue とは少し異なります。React には独自の状態管理方法がありません。実際には、js 関連の状態マネージャーを使用します。覚えておく必要があるのは、ビューによって状態が変化する可能性があり、状態の変化によってビューが再レンダリングされる可能性があるということです。

長々と話してきましたが、React で状態マネージャーをどのように使用すればよいのでしょうか?

Reduxが輝く

redux の前身の技術は flux です。これは flux と非常に似ていますが、まったく同じではありません。どちらも、モデルの更新ロジックを 1 つのレベル (Flux ではストア、redux ではリデューサー) に集中させる必要があると規定しています。ただし、redux にはディスパッチャーの概念がなく、イベント ハンドラーとして純粋な関数に依存しています。また、redux はデータを変更するために戻らず、状態を更新するための新しいオブジェクトを返します。

まず、reduxのプロパティをいくつか見てみましょう。

1. 店舗:

データ/状態を保存する場所。コンテナと考えることができます。アプリケーション全体でストアは 1 つしか存在できないことに注意してください。

'redux' から {createStore} をインポートします。
const ストア = createStore(fn)

2. 状態:

状態はストアのインスタンス オブジェクトと考えることができます。状態には状態マネージャー内のすべての状態が含まれており、特定の時点でのすべてのデータ/状態のコレクションです。

定数状態 = store.getState()

3. アクション

redux で最も重要なプロパティの 1 つです。ストアの状態を変更する唯一の方法は、アクションを送信することです。アクションは、type 属性を持つオブジェクトであり、通常は送信のキー値として使用されます。

定数アクション = {
    タイプ: 'ADD_TODO',
    ペイロード: 'Learc Redux' //ここでのペイロードはパラメータとして渡されるので、空白のままにしておくことができます}

4. store.dispatch():

アクションを送信する唯一の方法は、このように状態マネージャーに送信することです。後で他のどのような状態管理ツールが使用されるとしても、すべてこれに帰着します。

ストア.ディスパッチ({
    タイプ: 'ADD_TODO'
})

5. リデューサー:

アクションを受け取った後、ストアはビューが変更されるように新しい状態を返す必要があり、この状態の計算プロセスはリデューサーと呼ばれます。

リデューサーは、現在の状態とアクションを受け入れて新しい状態を返す関数です。

const リデューサー = (状態 = {
  count: 10 // 状態のプロパティの初期値を設定します。状態マネージャは更新ごとにクリアされるため、ローカルから最後に保存された値を初期値として取得できます。}, action) => {
  スイッチ(アクションタイプ){
    'REDUCE'の場合:
          // ここでは、アクションタイプの値を検索のキー値として使用していることがわかります。ディスパッチ時に、これらのキー値の判断に基づいて実行する操作を見つけることができます。 return { ...state, count: state.count - action.payload }
          //アクションの必要に応じて、元の状態を変更せずに元の状態に基づいた新しい状態オブジェクトを返します。
    ケース 'ADD':
      戻り値 { ...状態、カウント: state.count + action.payload }
   
    デフォルト:
      状態を返します。
  }
}
 
デフォルトのリデューサーをエクスポートする

新しい状態オブジェクトを返す方法は、ES6... 構文を介していることがわかります。このメソッドは少し複雑で低レベルのように思えますか?次に新しい方法を導入します。まず不変コンポーネントを導入します

このメソッドは、実際には JS でディープ コピーを実装し、元の状態オブジェクトのディープ コピーを作成します。このように、新しい状態オブジェクトへの変更は元の状態に影響を与えません。素晴らしいと思いませんか。 ! !

糸不変 -S を追加します

方向:

import { Map } from 'immutable' //Map関数を導入する const user = (state = Map({ //Mapを使用して状態を深くコピーする
  ログイン: localStorage.getItem('isLogin') === 'true'、    
  トークン: localStorage.getItem('token') || ''、
  管理者名: localStorage.getItem('管理者名') || ''、
  役割: localStorage.getItem('role') * 1 || 1
})、アクション) => {
  スイッチ(アクションタイプ){
    ケース 'CHANGE_LOGIN_STATE':
      return state.set('isLogin', action.payload) //設定モードでcase 'CHANGE_TOKEN'を記述します。
      state.set('token', action.payload) を返します。
    ケース 'CHANGE_ADMIN_NAME':
      state.set('adminname', action.payload) を返します。
    ケース 'CHANGE_ROLE':
      state.set('role', action.payload) を返します
    デフォルト:
      状態を返す
  }
}

デフォルトユーザーをエクスポート
状態 => {
    戻る {
        adminname: state.getIn(['user', 'adminname']), // get メソッドを使用して値を取得します。パラメータの形式は次のとおりです // 最初のパラメータの意味: 状態マネージャ内のユーザー // 2 番目のパラメータの意味: adminname という名前の状態/属性}
}

6. デザインステートマネージャー

まず、モジュール開発の考え方に基づいて、1 つのプロジェクトで複数のタイプのステータス マネージャーを設計し、最終的にそれらを 1 つに統合することができます。たとえば、商品のステータス、ユーザー情報のステータスなどです。

「redux」から createStore と combineReducers をインポートします。
// この combineReducers メソッドはモジュール開発の鍵です。モジュールのすべての状態マネージャーを結合するのに役立ちます。 import pro from './modules/pro'
'./modules/app' からアプリをインポートします
 
const Reducer = combineReducers({ //サブモジュールによって作成されたすべてのリデューサーをこのリデューサーに集中させる
  プロ、アプリ
})
 
const ストア = createStore(リデューサー)
 
デフォルトストアをエクスポート

舞台の解釈を手伝う

1 つ知っておくべきことがあります。特定の時点で状態を取得または変更したい場合、状態マネージャー ストアによって状態インスタンス オブジェクトが生成され、このインスタンス オブジェクトを操作できるようになります。状態が変化するとビューも変化しますが、ユーザーは状態にアクセスできずビューにしかアクセスできないため、状態の変化もビューによって引き起こされる必要があります。 ! !このアクションは、実際にはビューによって送信される通知です。ユーザーがビューを変更すると、この通知が送信され、状態を変更する必要があることがプログラムに通知されます。

//このように理解できます。発送、アクション、ストアの関係は、郵便局、メール、受信者として考えることができます。
//私たちは、仕事を見つけたので郵便局の助けが必要であることを伝える手紙(アクション)を送りたい。郵便局が手紙を受取人に届けるのを手伝ってくれると、受取人は私が伝えたい情報を受け取り、それに応じた変更を加える。
//ディスパッチを呼び出すと、タイプ(キー値)を通じて対応するメールが見つかり、ストアに送信されます

状態マネージャーはどのように使用されますか?

// プロバイダーと接続を介してコンポーネント内の状態マネージャーを「リンク」できます。リンクが成功すると、状態マネージャー内の状態とメソッドを使用できます。// /src/xxx/index.jsx
'react-redux' から {connect} をインポートします
 
関数App(プロパティ){
    ...
}
デフォルトの connect(mapStateToProps, mapDispatchToProps)(App) をエクスポートします。
     
// /index.js
'react-redux' から {Provider} をインポートします。
'./App.jsx' からアプリをインポートします
ストア './store/index.js' をインポートします
     
ReactDom.render (
    <React.StrictMode>
        <プロバイダーストア = {ストア}>
            <アプリ />
        </プロバイダー>
    </React.StrickMode>
)
 
//デコレータの高階関数 @connect @withRouter も使用できます
 
// 以前は、対応するデータは状態ツリーから取得され、 react-redux に付属する connect() メソッドを使用して props を通じてコン​​ポーネントに渡されていました。 class Home extends React.Component {
    //....
}
デフォルトの connect(state => ({todos: state.todos}))(Home) をエクスポートします。
 
//デコレータを使用すると、次のようになりますが、それほど複雑ではないようです @connect(state => ({ todos: state.todos }))
クラス Home は React.Component を拡張します {
    //....
}

ここではこのアプローチについて説明します。

状態マネージャーをリンクする必要があります。まず、プロジェクト全体のエントリ ファイル index.js に状態ストアを導入し、Provider メソッドを介してストアをパラメーターとして子コンポーネントに渡します。これは、祖先コンポーネントが子孫コンポーネントに値を渡す方法と多少似ています。

次に、状態マネージャーを使用して、connect 高階関数を介してコンポーネントに接続する必要があります。この高階関数の原理は、関数をパラメーターとして渡し、別の関数を返すことです。

マップ状態をプロパティに:

名前が示すように、state 内の状態トラバーサルを処理して props に格納することで、関数コンポーネント内の props パラメータ値で状態を取得できるようになります。

マップディスパッチプロパティ:

コンポーネント内の状態マネージャーで状態を変更できるように、submit メソッドを props の状態マネージャーに保存します。

const App = (props) => {
    // コンポーネントは、props を介して状態マネージャー内の状態 props.adminname に直接アクセスできます。
    小道具の数
    props.bannerList
    プロパティ
    ...
}
エクスポートデフォルト接続(
    // ここでは 2 つの関数が渡され、2 つの関数が返されることがわかります。state => {
        戻る {
            adminname: state.getIn(['user', 'adminname']), //これは状態を保存する方法です。countについては後で説明します: state.app.count, //パラメータはstateです。アプリ状態マネージャのcountプロパティをpropsのcountに渡します。
            バナーリスト: state.pro.bannerList、
        }
    },
    ディスパッチ => {
        戻る {
            ReduceFn () { // ここで、dispatch メソッドを含む ReduceFn を定義します。props の ReduceFn メソッドを使用して、'REDUCE' によって送信された情報を送信できます。dispatch({
                    タイプ: 'REDUCE'、
                    ペイロード: 5 //ペイロードはパラメータなので省略可能})
            }
        }
    }
)(アプリ)

状態を変更するこの基本的な方法に加えて、いくつかのツールを使用することもできます

redux-thunk、redux-saga

redux-thunkの使用

//store.js に thunk を導入し、それを状態マネージャーにマウントします。import { createStore, combineReducers, applyMiddleware} from 'redux'
 
'redux-thunk' から thunk をインポートします
'./modules/app' からアプリをインポートします
'./modules/pro' から pro をインポートします
 
定数リデューサー = 結合リデューサー({
  アプリ、プロ
})
//applyMiddleware を通じて状態マネージャーに thunk をマウントします。const store = createStore(reducer, applyMiddleware(thunk))
 
デフォルトストアをエクスポート

次に、非同期メソッドを含む状態を変更する方法をカプセル化する別のファイルを設計します。

// .../store/actionCreator/pro.js
 
// このファイルは非同期操作をトリガーするために特に使用されます // thunk モジュールが実行されると、actionCreator 関数にはデフォルトのパラメータとして dispatch が設定されます
// このディスパッチはリデューサーをトリガーするために使用できます
// 非同期をトリガーするときに、パラメータを渡す必要がある場合があります。この場合、関数内でactionCreator関数を返すことができます。const actions = {
  getBannerListAction (ディスパッチ) {
    フェッチ('http://121.89.205.189/api/banner/list')
    .then(res => res.json())
    .then(res => {
      急送({
        タイプ: 'CHANGE_BANNER_LIST',
        ペイロード: res.data
      })
    })
  },
  getProListAction (count) { //パラメータ付きで関数を返す。関数パラメータのデフォルトはdispatch
    カウント = カウント || 1
    関数を返す(ディスパッチ){
      フェッチ('http://121.89.205.189/api/pro/list?count=' + カウント)
      .then(res => res.json())
      .then(res => {
        急送({
          タイプ: 'CHANGE_PRO_LIST'、
          ペイロード: res.data
        })
      })
    }
  }
}
 
デフォルトのアクションをエクスポートする

上記の手順は、アクションを送信するためのいくつかのディスパッチを含むアクション オブジェクトの定義と見なすことができます。コンポーネントの状態を変更する場合は、このオブジェクトの関数を直接使用できます。関数は自動的にリクエストを開始し、アクションを送信します。

また、dispatch(actions.getBannerListAction) している次のコンポーネントの使用からもわかります。実際には、これはアクションを送信する形式ですが、アクションの変更と非同期リクエストをカプセル化しています。

'./store/actionCreator/pro' からアクションをインポートします
const App = (props) => {
    // props.reduceFn() は props から直接アクセスできます
    プロパティを追加します。
    props.getBannerList()
    props.getProList()
}
 
const mapStateToProps = (状態) => {
  戻る {
    カウント: state.app.count、
    バナーリスト: state.pro.bannerList、
    プロリスト: state.pro.proList
  }
}
 
const mapDispatchToProps = (ディスパッチ) => {
  戻る {
    ReduceFn () { //通常の方法で状態を変更するdispatch({       
        タイプ: 'REDUCE'、
        ペイロード: 5
      })
    },
    追加関数() {
      急送({
        タイプ: 'ADD'、
        ペイロード: 5
      })
    },
    getBannerList () { // thunkメソッドdispatch(actions.getBannerListAction)を通じてステータスを変更します
    },
    プロリストを取得する() {
      ディスパッチ(actions.getProListAction(2))
    }
  }
}
 
デフォルトの connect(mapStateToProps, mapDispatchToProps)(App) をエクスポートします。

リンク方法は通常のreact-reduxと全く同じで、最終的にアクションをディスパッチすることで状態が変更されます。

react-sagaの使用

redux-sagaをインストールする

糸を redux-saga 不変 redux-immutable -S に追加します

redux-saga と redux-thunk は、dispatch を送信する方法と考えることができます。昔は、車や徒歩で手紙 (dispatch) を送信していましたが、ツールを使用すると、電車や飛行機で手紙を送信するのと同じになります。

'redux' から { createStore、combineReducers、applyMiddleware } をインポートします。
 
'redux-saga' から createSagaMiddleware をインポートします。
 
import mySaga from './mySaga' //非同期操作命令 import home from './modules/home'
'./modules/app' からアプリをインポートします
 
定数リデューサー = 結合リデューサー({
  アプリ、
  家
})
 
const sagaMiddleware = createSagaMiddleware() // saga ミドルウェアを生成 const store = createStore(reducer, applyMiddleware(sagaMiddleware))
//リンクを確立します //thunk と同様に、saga ミドルウェアを状態マネージャーにマウントし、saga メソッドを使用して状態を変更できます sagaMiddleware.run(mySaga)
//run: Send // これは、状態エクスポートのデフォルトストアを変更する関数としてカプセル化されたmySage関数です

次に、サガがどのように状態を変更するかを紹介します。

redux-sagaでは、Generator関数を使用して状態が変更されます。

'redux-saga/effects' から { call, put, takeLatest } をインポートします。
 
'../api/home' から { getBannerList, getProList } をインポートします。
 
// redux-saga ---> ジェネレータ関数と一緒に使用する必要があります function * getBannerListAction() {
  const res = yield call(getBannerList) //call--関数を呼び出す yield put({
    タイプ: 'CHANGE_BANNER_LIST',
    ペイロード: res.data
  })
}
関数 * getProListAction (アクション) {
  const res = yield call(getProList, action.payload)
  イールドプット({
    タイプ: 'CHANGE_PRO_LIST'、
    ペイロード: res.data
  })
}
 
関数 * mySaga() {
  takeLatest('REQUEST_BANNER_LIST', getBannerListAction) を取得します。
  takeLatest('REQUEST_PRO_LIST', getProListAction) を取得します。
}
 
デフォルトのエクスポート mySaga

上記が理解できなくても、恐れることはありません。ここを見て

// mysagaファイルでは、送信メソッドを定義します。import { takeLatest } from 'redux-saga/effects'
// takeLatest --- タスクを割り当てます。以下。キーを定義し、それにイベントを割り当てます。これらのイベントは、store.dispatch() 関数で使用される関数です。 * getProListAction (action){
  const res = yield call(getProList, action.payload)
  イールドプット({
    タイプ: 'CHANGE_PRO_LIST'、
    ペイロード: res.data
  })
}
関数 * mySaga() {
  takeLatest('REQUEST_PRO_LIST', getProListAction) を取得します。
}
 
// 将来的にステータスを変更したい場合、store.dispatch() を使用して変更する必要はありません。 // このファイルで定義されたキー値を使用して変更できます。 // コンポーネントの connect で次のようにカスタム関数を定義し、キー値に応じてここで変更メソッドの dispatch を直接呼び出します => {
    ディスパッチ({ タイプ: 'REQUEST_PRO_LIST'})
}
 
 
// 置く、呼び出す
// call ---> は呼び出すことを意味します // put ---> はプッシュすることを意味します。現在のアクションを次に実行されるアクション (キュー) にプッシュします。
 
yield put(アクション)
呼び出し(fn)

上記は、React でよく使われるステートマネージャーについて、さまざまなドキュメントに基づいて私が理解した内容です。間違いがあれば、ご指摘いただければ、一緒に前進していけたらと思います。

上記の状態マネージャーに加えて、MobX、Umi、Dva などのツールも市場に出回っています。時間があれば、それらを整理して皆さんと共有したいと思います。

React のさまざまな状態マネージャーの解釈に関するこの記事はこれで終わりです。React 状態マネージャーに関するより関連性の高いコンテンツについては、123WORDPRESS.COM の過去の記事を検索するか、以下の関連記事を引き続き参照してください。今後とも 123WORDPRESS.COM をよろしくお願いいたします。

以下もご興味があるかもしれません:
  • React のグローバル状態管理の 3 つの基本メカニズムの調査
  • Reactの状態管理の3つのルールのまとめ
  • ReactでVueの状態管理メソッドを使用する例

<<:  ブラウザの自動フォーム入力によるウェブページのスタイル損失の原因の分析と解決

>>:  HTML で自動ページジャンプを実現する 5 つの方法

推薦する

HTML における要素の水平および垂直中央揃えに関する議論

ページをデザインするときには、ログイン ウィンドウを中央に配置するなど、DIV を中央に配置し、ペー...

Docker構成 Alibaba Cloud Container Serviceの操作

Alibaba Cloud Dockerコンテナサービスの設定Alibaba Cloud Image...

MySQL インデックスの設計と最適化の方法

目次インデックスとは何ですか?左端のプレフィックス一致の原則key_lenの計算方法インデックスの最...

マウスのドラッグ効果を実現するJavaScript

この記事では、マウスドラッグ効果を実現するためのJavaScriptの具体的なコードを参考までに紹介...

MySQLクエリのパフォーマンスに影響を与える大きなオフセットの理由と最適化の詳細な説明

序文MySQL クエリは select コマンドを使用し、limit および offset パラメー...

Vueでタイマーをエレガントにクリアする方法

目次序文最適化派生的な質問: beforeDestroy はトリガーされませんか?序文タイマーをクリ...

電子メールの HTML ページを作成するための原則の概要

HTML メールはこのサイト上の独立したホスト ページではないため、他の誰かによってホストされていま...

JavaScript スコープチェーンの基本原理のグラフィカルな説明

目次序文範囲1. スコープとは何ですか? 2. [[スコープ]] プロパティ3. スコープチェーン4...

Windows Server 2016 リモート デスクトップ サービスを展開するためのクイック スタート ガイド

現在、2016サーバーは、win2008や2012よりも優れたマルチサイトhttpsサービスをサポー...

ウェブページに埋め込まれた Flash と IE、FF、Maxthon の互換性の問題

いろいろ苦労した後、インターネットで検索したり、以前の会社のプロジェクトを探したり、他の人のプロジェ...

Nginxリバースプロキシ設定でプレフィックスが削除される

nginx をリバース プロキシとして使用する場合、リクエストをそのまま次のサービスに転送するだけで...

Dockerサーバーのストレージリソースプール不足問題の解決

目次1. 問題の説明2. 問題分析3. 問題解決1. Dockerのディスク使用量を確認する2. 再...

CocosCreator でカメラトラッキングに cc.follow を使用する方法

Cocos Creator バージョン: 2.3.4デモのダウンロード: https://files...

Centos7サーバーの基本的なセキュリティ設定手順

pingスキャンをオフにする(役に立たないが)まずルートに切り替えるエコー 1 > /proc...

Alipay の新しいホームページのフロントエンドの実践的な概要

もちろん、ページ パフォーマンスの最適化に関する個人的な経験も含まれています。ここでいくつかの点につ...