メモ
22620 ワード
React状態管理ツール
Redux
1.Reduxコア
1.1 Redux紹介
JavaScript状態容器は、予測可能な状態管理を提供します.
1.2 Reduxコア概念とフロー
Store:格納状態のコンテナ、JavaScriptオブジェクトView:ビュー、HTMLページアクション:オブジェクト、状態に対してどのような操作が行われているかを記述し、Reducers:関数、操作状態を説明し、新しい状態に戻ります.
1.3 Redux使用:カウンタケース
2.1 ReactでReduxを使わない時に発生した問題
Reactではコンポーネント通信のデータストリームは一方向であり、トップのコンポーネントはProps属性によって下部のコンポーネントにデータを転送することができ、下部のコンポーネントは上部のコンポーネントにデータを転送することができない.下のコンポーネントでデータを修正するには、上のコンポーネントから下のコンポーネントに修正データを転送する方法が必要です.プロジェクトがますます大きくなると、コンポーネント間のデータ転送が難しくなります.
2.2 ReactプロジェクトにReduxを加えるメリット
Reduxを使用してデータを管理し、Storeはコンポーネントと独立しているため、データ管理がコンポーネントと独立し、コンポーネントとコンポーネントの間でデータを転送するのが困難な問題を解決した.
2.3ダウンロードReduxコンポーネントは、dispach方法によってアクションをトリガする . Storeはアクションを受け取り、アクションをReducer に配信する. Reducerは、アクションタイプに従って状態を変更し、変更された状態をStore に戻す.コンポーネントはStoreの状態を購読しています.Storeの状態更新はコンポーネント に同期されます.
2.5 Redux使用手順
2.5.1 storeを作成するリレーパラメータ は、パラメータを受け取り、 を伝える. を処理する.
2.6 reduxポップアップブロックの判例を実現する
src/index.js
src/store/reducers/root.reducer.js
3.1中間部品とは何ですか?
中間価格は私達がreduxアプリケーションを拡張し、強化することができます.
3.2 Redux中間部品の開発
中間部品のテンプレートを開発する
中間部品は開発が完了した後、登録されてこそ、Reduxのワークフローで有効になります.
src/store/index.js
3.4 Redux中間部品開発例thunk(非同期中間部品)
現在のこの中間関数は、どのような非同期操作を実行したいのかに関心がなく、ただ非同期操作を実行しているかに関心があります.もしあなたが実行しているのが非同期操作であれば、actionをトリガする時に、関数を伝えてください.もし実行しているのが同期操作なら、actionオブジェクトを伝達します.非同期の操作コードは、あなたが送ってきた関数の中に書いてください.この中間部品の関数は、あなたが送ってきた関数を呼び出した時に、dispach方法を過去のsrc/store/middleware/thunk.jsに伝えます.
src/store/actions/modal.actions.js
4.Redux常用ミドルウェア
4.1 redux-thunk
4.1.1 redux-thunkダウンロード
4.2.1 redux-saga解決の問題
4.2.2ダウンロードredux-saga
src/store/index.js
src/store/index.js
src/store/sagas/counter.saga.js
src/store/index.js
src/store/saga/root.saga.js
src/store/saga/modal.saga.js
src/store/index.js
4.3.1 redux-actions解決の問題
reduxプロセスの中で大量のサンプルコードは読み书きに苦しみます.redux-actionを使ってアクションとReducerの処理を简略化できます.
4.3.2 redux-actionのダウンロード
src/store/actions/counter.actions.js
MobX
1.Mobx概要
1.1 Mobxの紹介
簡単、拡張可能な状態管理ライブラリ
MobxはMendix(コード開発プラットフォーム)、Coinbase(ビットコイン会社)、フェイスブックのソースと多くの個人スポンサーによって協賛されているReactとMobxのペアで、Reactはアプリケーションの状態をレンダリングし、Mobxはアプリケーションの状態を管理してReactに使用されます.
1.2 MobXブラウザサポート
MobX 5バージョンはES 6 Proxyをサポートするブラウザで実行されています.IE 11はサポートされていません.Node.js 6 MobX 4はES 5をサポートするブラウザで実行できます.MobX 4と5のAPIは同じです.
2.開発前の準備
2.1飾り器の文法サポートを有効にする(方式一)弾射項目の下の構成: 装飾器文法Babelプラグインをダウンロードする: は、package.jsonファイルにプロファイル を追加する. プロジェクトのルートディレクトリの下でconfig-overrides.jsを作成し、構成 を追加する. package.json 3.Mobx+React
3.1 Mobxをダウンロードする
アクション->state->View
5.Mobxデータ監視
5.1 computed計算値
いつ計算値を使って複雑な業務ロジックをテンプレートから抜き出しますか?
5.2 autrun方法
傍受の状態が変化すると、状態によって「効果」が発生しますので、atorun.atorunを使って初期化時に一回実行してください.状態が変化するたびに実行します.
Redux
1.Reduxコア
1.1 Redux紹介
JavaScript状態容器は、予測可能な状態管理を提供します.
1.2 Reduxコア概念とフロー
Store:格納状態のコンテナ、JavaScriptオブジェクトView:ビュー、HTMLページアクション:オブジェクト、状態に対してどのような操作が行われているかを記述し、Reducers:関数、操作状態を説明し、新しい状態に戻ります.
1.3 Redux使用:カウンタケース
Redux
0
// 3.
const initialState = {
count: 0
}
// 2. reducer
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;
}
}
// 1. store
const store = Redux.createStore(reducer);
// 4. action
const increment = { type: 'increment' }
const decrement = { type: 'decrement' }
// 5.
document.getElementById('minus')
.addEventListener('click', function () {
// 6. dispatch action
store.dispatch(decrement)
})
document.getElementById('plus')
.addEventListener('click', function () {
// 6. dispatch action
store.dispatch(increment)
})
// store {dispatch: ƒ, subscribe: ƒ, getState: ƒ, replaceReducer: ƒ, Symbol(observable): ƒ}
console.log(store)
// store state
console.log(store.getState());
//
store.subscribe(() => {
console.log(store.getState())
document.getElementById('count').innerHTML = store.getState().count
});
1.4 ReduxコアAPI// store
const store = Redux.createStore(reducer);
// 2. reducer
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;
}
}
// store state
store.getState()
//
store.subscribe(() => {
console.log(store.getState())
});
// dispatch action
store.dispatch(increment)
2.React+Redux2.1 ReactでReduxを使わない時に発生した問題
Reactではコンポーネント通信のデータストリームは一方向であり、トップのコンポーネントはProps属性によって下部のコンポーネントにデータを転送することができ、下部のコンポーネントは上部のコンポーネントにデータを転送することができない.下のコンポーネントでデータを修正するには、上のコンポーネントから下のコンポーネントに修正データを転送する方法が必要です.プロジェクトがますます大きくなると、コンポーネント間のデータ転送が難しくなります.
2.2 ReactプロジェクトにReduxを加えるメリット
Reduxを使用してデータを管理し、Storeはコンポーネントと独立しているため、データ管理がコンポーネントと独立し、コンポーネントとコンポーネントの間でデータを転送するのが困難な問題を解決した.
2.3ダウンロードRedux
npm install redux react-redux
2.4 Reduxワークフロー2.5 Redux使用手順
2.5.1 storeを作成する
// src/store/index.js
import { createStore } from 'redux'
import reducer from './reducers/counter.reducer'
export const store = createStore(reducer)
ルートコンポーネントにstore
を使用する.import React from 'react';
import ReactDOM from 'react-dom';
import Counter from './components/Counter'
import { Provider } from 'react-redux'
import {store} from './store'
/**
* react-redux
* Provider
* connect
*/
ReactDOM.render(
// provider , store
,
document.getElementById('root')
);
2.5.2 reducerを作成する// src/store/reducers/counter.reducer.js
import { DECREMENT, INCREMENT } from "../count/counter.const";
const initialState = {
count: 0
}
export default 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;
}
}
// src/store/count/counter.const.js
export const INCREMENT = 'increment'
export const DECREMENT = 'decrement'
2.5.3コンポーネントの中でconnectを使ってstoreの中のstateとdispatchを受け入れます.connect
方法は、2つのパラメータを受け取り、高次のコンポーネントを返す.connect
方法の最初のパラメータはmapStateToProps
方法であり、storeのstateをコンポーネントのprops
に伝達し、mapStateToProps
方法のパラメータはstate
であり、戻り値はオブジェクトであり、コンポーネントに伝達される.const mapStateToProps = (state) => ({
count: state.count,
a: 'a', // ,
})
connect
方法の2番目のパラメータはmapDispatchToProps
方法であり、store
のdispatch
をコンポーネントのprops
に伝達し、mapDispatchToProps
方法のパラメータはdispatch
であり、戻り値はオブジェクトであり、オブジェクト内の方法はdispatch
を使用してもよく、このオブジェクト内の方法はコンポーネントに伝達される.const mapDispatchToProps = (dispatch) => ({
increment () {
dispatch({ type: 'increment'})
},
decrement () {
dispatch({ type: 'decrement' })
}
})
また、redux
のbindActionCreators
を介して、action
関数を作成しても良いです.import {bindActionCreators} from 'redux'
// bindActionCreators
const mapDispatchToProps = dispatch => (
//
...bindActionCreators({
increment () {
return { type: 'increment'}
},
decrement () {
return { type: 'decrement'}
}
}, dispatch)
)
または作成:const mapDispatchToProps = dispatch => bindActionCreators({
increment () {
return { type: 'increment'}
},
decrement () {
return { type: 'decrement'}
}
}, dispatch)
bindActionCreators
の最初のパラメータをオフにしてもよい.import * as counterActions from '../store/actions/counter.actions'
const mapDispatchToProps = dispatch => bindActionCreators(conterActions, dispatch)
// src/store/actions/counter.actions.js
import { DECREMENT, INCREMENT } from "../count/counter.const"
export const increment = () => ({type: INCREMENT})
export const decrement = () => ({type: DECREMENT})
connect
方法は、mapStateToProps
およびmapDispatchToProps
を受け取り、高次のコンポーネントに戻り、Counter
のコンポーネントに導かれる.export default connect(mapStateToProps, mapDispatchToProps)(Counter)
最終コンポーネントコードは以下の通りです.// src/components/Counter.js
import React from 'react'
import {connect} from 'react-redux'
import {bindActionCreators} from 'redux'
import * as counterActions from '../store/actions/counter.actions'
function Counter ({count, increment, decrement}) {
return (
{count}
)
}
// 1. connect store, store ,
// 2. connect store , props
// 3. connect dispatch
const mapStateToProps = (state) => ({
count: state.count,
a: 'a', // ,
})
const mapDispatchToProps = dispatch => bindActionCreators(counterActions, dispatch)
export default connect(mapStateToProps, mapDispatchToProps)(Counter)
2.5.4 action伝達パラメータ
reducer
export const increment = payload => ({type: INCREMENT, payload})
export const decrement = payload => ({type: DECREMENT, payload})
reducer
は、受信したデータに基づいてexport default function reducer (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;
}
}
2.6 reduxポップアップブロックの判例を実現する
store
中の状態が多いほど、reducer
中のswitch
分岐は多くなり、維持に不利で、reducer
を分割する必要がある.src/index.js
// src/index.js
import React from 'react';
import ReactDOM from 'react-dom';
import App from './App';
import { Provider } from 'react-redux'
import {store} from './store'
ReactDOM.render(
// provider , store
,
document.getElementById('root')
);
src/store/index.js// src/store/index.js
import { createStore } from 'redux'
import reducer from './reducers/counter.reducer'
export const store = createStore(reducer)
src/store/reducers/counter.reducer.js// src/store/reducers/counter.reducer.js
import { DECREMENT, INCREMENT } from "../const/counter.const";
import { HIDEMODAL, SHOWMODAL } from "../const/modal.const";
const initialState = {
count: 0,
show: false
}
export default function reducer (state = initialState, action) {
switch (action.type) {
case INCREMENT:
return { ...state, count: state.count + action.payload };
case DECREMENT:
return { ...state, count: state.count - action.payload };
case SHOWMODAL:
return { ...state, show: true };
case HIDEMODAL:
return { ...state, show: false };
default:
return state;
}
}
src/App.js// src/App.js
import Modal from './components/Modal'
import Counter from './components/Counter'
function App() {
return (
);
}
export default App;
src/components/Modal.js// src/components/Modal.js import React from 'react' import { connect } from 'react-redux' import { bindActionCreators } from 'redux' import * as modalActions from '../store/actions/modal.actions' function Modal ({ showStatus, show, hide }) { const styles = { display: showStatus ? 'block': 'none', width: 200, height: 200, position: 'absolute', top: 0, right: 0, bottom: 0, left: 0, margin: 'auto', backgroundColor: 'skyblue' } return (
) } const mapStateToProps = state => ({ showStatus: state.show }) const mapDispatchToProps = dispatch => bindActionCreators(modalActions, dispatch) export default connect(mapStateToProps, mapDispatchToProps)(Modal)
src/store/actions/modal.action.js
// src/store/actions/modal.action.js
import { HIDEMODAL, SHOWMODAL } from "../const/modal.const"
export const show = () => ({ type: SHOWMODAL })
export const hide = () => ({ type: HIDEMODAL })
src/store/const/modal.co nst.js// src/store/const/modal.const.js
export const SHOWMODAL = 'showModal'
export const HIDEMODAL = 'hideModal'
2.7分割reducer
reducer
によって提供されるツールcombineReducers
を使用して、それぞれの小さなreducer
をマージする.src/store/reducers/root.reducer.js
// src/store/reducers/root.reducer.js
import {combineReducers} from 'redux'
import CounterReducer from './counter.reducer'
import ModalReducer from './modal.reducer'
// { counter: { count: 0 }, modal: { show: false } }
export default combineReducers({
counter: CounterReducer,
modal: ModalReducer
})
src/store/reducers/counter.reducer.js// src/store/reducers/counter.reducer.js
import { DECREMENT, INCREMENT } from "../const/counter.const";
const initialState = {
count: 0,
}
export default function counterReducer (state = initialState, action) {
switch (action.type) {
case INCREMENT:
return { ...state, count: state.count + action.payload };
case DECREMENT:
return { ...state, count: state.count - action.payload };
default:
return state;
}
}
src/store/reducers/modal.reducer.js// src/store/reducers/modal.reducer.js
import { HIDEMODAL, SHOWMODAL } from "../const/modal.const";
const initialState = {
show: false
}
export default function modalReducer (state = initialState, action) {
switch (action.type) {
case SHOWMODAL:
return { ...state, show: true };
case HIDEMODAL:
return { ...state, show: false };
default:
return state;
}
}
store
を作成するときに入ってきたreducer
は、私たちが先ほど定義したroot.reducer.js
から来ています.import { createStore } from 'redux'
import RootReducer from './reducers/root.reducer'
export const store = createStore(RootReducer)
各コンポーネントのmapStateToProps
においても、対応する変更が発生する(state.counter
およびstate.modal
).const mapStateToProps = (state) => ({
count: state.counter.count,
})
const mapStateToProps = state => ({
showStatus: state.modal.show
})
3.Redux中間部品3.1中間部品とは何ですか?
中間価格は私達がreduxアプリケーションを拡張し、強化することができます.
3.2 Redux中間部品の開発
中間部品のテンプレートを開発する
export default store => next => action => { }
3.3中間部品を登録する中間部品は開発が完了した後、登録されてこそ、Reduxのワークフローで有効になります.
src/store/index.js
// src/store/index.js
import { createStore, applyMiddleware } from 'redux'
import logger from './middlewares/logger'
createStore(reducer, applyMiddleware(
logger
))
src/store/middleware/logger.jsconst logger = store => next => action => {
console.log(store)
console.log(action)
next(action) // next(action)
}
export default logger
複数の中間部品を登録する場合、中間部品の実行順序は登録順序です.createStore(reducer, applyMiddleware(
logger,
test
))
実行順序は、logger
ミドルウェアを先に実行し、test
ミドルウェアを実行することである.中間部品の終わりにnext(action)
を起動しないと、フロー全体はここでカードになります.これ以上実行しません.3.4 Redux中間部品開発例thunk(非同期中間部品)
現在のこの中間関数は、どのような非同期操作を実行したいのかに関心がなく、ただ非同期操作を実行しているかに関心があります.もしあなたが実行しているのが非同期操作であれば、actionをトリガする時に、関数を伝えてください.もし実行しているのが同期操作なら、actionオブジェクトを伝達します.非同期の操作コードは、あなたが送ってきた関数の中に書いてください.この中間部品の関数は、あなたが送ってきた関数を呼び出した時に、dispach方法を過去のsrc/store/middleware/thunk.jsに伝えます.
// src/store/middleware/thunk.js
import { DECREMENT, INCREMENT } from "../const/counter.const";
const thunk = ({dispatch}) => next => action => {
if (typeof action === 'function') {
return action(dispatch) // action dispatch
}
next(action)
}
export default thunk
非同期関数actionをactionファイルに定義します.src/store/actions/modal.actions.js
// src/store/actions/modal.actions.js
import { HIDEMODAL, SHOWMODAL } from "../const/modal.const"
export const show = () => ({ type: SHOWMODAL })
export const hide = () => ({ type: HIDEMODAL })
export const show_async = () => dispatch => {
setTimeout(() => {
dispatch(show())
}, 2000);
}
元々はshow
を使っていたところをshow_async
に切り替え、非同期の機能を実現しました.4.Redux常用ミドルウェア
4.1 redux-thunk
4.1.1 redux-thunkダウンロード
npm install redux-thunk
4.1.2 redux-thunkの導入import thunk from 'redux-thunk';
4.1.3 redux-thunkを登録するimport { applyMiddleware } from 'redux'
createStore(rootReducer, applyMiddleware(thunk));
4.1.4 redux-thunk中間部品を使用するconst loadPosts = () => async dispatch => {
const posts = await axios.get('/api/posts').then(response => response.data);
dispatch({type: LOADPOSTSSUCCE, payload: posts});
}
4.2 redux-saga4.2.1 redux-saga解決の問題
redux-saga
は、非同期動作をAction Creator
ファイルから引き出して、別個のファイルに置くことができる.4.2.2ダウンロードredux-saga
npm install redux-saga
4.2.3レdux-sagaミドルウェアを作成するsrc/store/index.js
// src/store/index.js
import createSagaMiddleware from 'redux-saga';
const sagaMiddleware = createSagaMiddleware();
4.2.4サイガミドレワに登録するsrc/store/index.js
// src/store/index.js
createStore(reducer, applyMiddleware(sagaMiddleware))
4.2.5 sagaを使ってaction非同期を受け入れて操作を実行するsrc/store/sagas/counter.saga.js
// src/store/sagas/counter.saga.js
import { takeEvery, put, delay } from 'redux-saga/effects'
import { increment } from '../actions/counter.actions'
import { INCREMENT_ASYNC } from '../const/counter.const'
// takeEvery action
// put action
function * increment_async_fn (action) {
yield delay(2000) // 2
yield put(increment(action.payload))
}
export default function * counterSaga () {
// action
yield takeEvery(INCREMENT_ASYNC, increment_async_fn) // action
}
src/store/actions/counter.actions.js// src/store/actions/counter.actions.js
// saga
export const increment_async = (payload) => ({ type: INCREMENT_ASYNC, payload });
src/store/const/counter.co nst.js// src/store/const/counter.const.js
export const INCREMENT_ASYNC = 'increment_async'
src/components/Counter.js
4.2.6サガを起動するsrc/store/index.js
// src/store/index.js
import counterSaga from './sagas/counter.saga'
sagaMiddleware.run(counterSaga);
4.2.7合併sagasrc/store/saga/root.saga.js
// src/store/saga/root.saga.js
import { all } from 'redux-saga/effects'
import counterSaga from './counter.saga'
import modalSaga from './modal.saga'
export default function * rootSaga () {
yield all([
counterSaga(),
modalSaga()
])
}
modal.saga.jsは変わりません.modal.saga.jsは以下の通りです.src/store/saga/modal.saga.js
// src/store/saga/modal.saga.js
import { takeEvery, put, delay } from 'redux-saga/effects'
import { show } from '../actions/modal.actions'
import { SHOWMODAL_ASYNC } from '../const/modal.const'
// takeEvery action
// put action
function * showModal_async_fn () {
yield delay(2000)
yield put(show())
}
export default function * modalSaga () {
// action
yield takeEvery(SHOWMODAL_ASYNC, showModal_async_fn)
}
store入口ファイルのsagaミドルウェア起動root.sagasrc/store/index.js
// src/store/index.js
import rootSaga from './sagas/root.saga'
sagaMiddleware.run(rootSaga)
4.3 redux-actions4.3.1 redux-actions解決の問題
reduxプロセスの中で大量のサンプルコードは読み书きに苦しみます.redux-actionを使ってアクションとReducerの処理を简略化できます.
4.3.2 redux-actionのダウンロード
npm install redux-actions
4.3.3アクションを作成するimport { createAction } from 'redux-actions'
const increment_action = createAction('increment');
const decrement_action = createAction('decrement');
4.3.4 Reducerを作成するsrc/store/actions/counter.actions.js
src/store/actions/counter.actions.js
// redux-actions
import { createAction } from 'redux-actions'
export const increment = createAction('increment')
export const decrement = createAction('decrement')
src/store/reducers/counter.reducer.js// src/store/reducers/counter.reducer.js
import { handleActions as createReducer } from 'redux-actions'
import { increment, decrement } from '../actions/counter.actions'
const initialState = {
count: 0,
}
const handleIncrement = (state, action) => ({
count: state.count + action.payload
})
const handleDecrement = (state, action) => ({
count: state.count - action.payload
})
export default createReducer({
[increment]: handleIncrement,
[decrement]: handleDecrement,
}, initialState)
コンポーネント使用:src/components/Counter.js// src/components/Counter.js
function Counter ({count, increment, decrement}) {
return (
{count}
)
}
redux-actionsはredux-sagaにも結合して使用できます.MobX
1.Mobx概要
1.1 Mobxの紹介
簡単、拡張可能な状態管理ライブラリ
MobxはMendix(コード開発プラットフォーム)、Coinbase(ビットコイン会社)、フェイスブックのソースと多くの個人スポンサーによって協賛されているReactとMobxのペアで、Reactはアプリケーションの状態をレンダリングし、Mobxはアプリケーションの状態を管理してReactに使用されます.
1.2 MobXブラウザサポート
MobX 5バージョンはES 6 Proxyをサポートするブラウザで実行されています.IE 11はサポートされていません.Node.js 6 MobX 4はES 5をサポートするブラウザで実行できます.MobX 4と5のAPIは同じです.
2.開発前の準備
2.1飾り器の文法サポートを有効にする(方式一)
npm run eject
npm install @babel/plugin-proposal-decorators
"babel": {
"plugins": [
[
"@babel/plugin-proposal-decorators",
{
"legacy": true
}
]
]
}
装飾器文法サポートを有効にします.npm install react-app-rewired customize-cra @babel/plugin-proposal-decorators
const { override, addDecoratorsLegacy } = require("customize-cra");
module.exports = override(addDecoratorsLegacy());
"scripts": {
"start": "react-app-rewired start",
"build": "react-app-rewired build",
"test": "react-app-rewired test"
}
2.2 vscodeエディタの飾り文法に関する警告を解決して、vscodeでcommand+カンマを押して、入力ボックスにjavascript.implicitProjectConfig.experimentalDecorators
を入力して構成を変更します."javascript.implicitProjectConfig.experimentalDecorators": true
3.1 Mobxをダウンロードする
npm install mobx mobx-react
3.2 Mobx作業フローアクション->state->View
5.Mobxデータ監視
5.1 computed計算値
いつ計算値を使って複雑な業務ロジックをテンプレートから抜き出しますか?
5.2 autrun方法
傍受の状態が変化すると、状態によって「効果」が発生しますので、atorun.atorunを使って初期化時に一回実行してください.状態が変化するたびに実行します.