經過閱讀阮一峯老師的redux教程,終於把redux理解了個大概,在這裏記錄一下。如下均爲我的理解內容。原文戳這裏javascript
使用 create-react-app 建立 react 項目css
安裝 redux react-reduxhtml
安裝 redux-thunk 中間件java
建立 store 文件夾, 並建立 index.jsreact
import {createStore, applyMiddleware, compose} from 'redux'
import reducer from '../reducers/index'
import thunk from 'redux-thunk'
const defaultState = {}
const store = createStore( // 調用 createStore 函數生成一個 store
reducer, // 將 reducer 傳入,這個 reducer 能夠是多個 reducer 的集合
defaultState, // 傳入默認的 state
compose(
applyMiddleware(thunk), // 使用 thunk 中間件,使 action 可以返回一個函數(必需)
window.__REDUX_DEVTOOLS_EXTENSION__ && window.__REDUX_DEVTOOLS_EXTENSION__() // 使用瀏覽器插件
)
)
export default store
複製代碼
在 index.js 中引入 Provider 將 全局的 App組件包起來,並傳入 storegit
import {Provider} from 'react-redux'
import store from './store/index'
ReactDOM.render(
<Provider store={store}>
<App />
</Provider>,
document.getElementById('root')
);
複製代碼
建立 components 文件夾,並定義 Counter 組件github
import React, { Component } from 'react'
import {connect} from 'react-redux'
import {sub, add} from '../actions/action'
export class Counter extends Component {
render() {
return (
<div>
<button style={{fontSize: 30}} onClick={this.props.sub}>-</button> {/* this.props.sub 能夠調用到 action.js 中的 sub 方法, 這時會打印 ‘觸發了sub’*/}
<span style={{padding: '0 30px'}}>{this.props.num}</span> {/* this.props.num 其實是獲取的 reducer.js 中的 state 中的 num,這裏經過下面的 connect 中的 mapStateToProps 從新轉化獲得 */}
<button style={{fontSize: 30}} onClick={this.props.add}>+</button>
</div>
)
}
}
const mapStateToProps = state => { // 這裏的 state 至關於 store,store 至關於一個大 state,這個 state 中又包含多個小的 state(即 reducer.js),小的 state 中包含各自的數據
return {
num: state.reducer.num
}
}
export default connect(mapStateToProps,{sub, add})(Counter)
// connect 將當前組件和 state,action 聯繫起來,使得能夠在組件中調用action中的方法和state中的數據
// connect 方法傳入 mapStateToProps 和 mapDispatchToProps 兩個參數,這兩個參數均爲對象
// mapStateToProps,將 state 轉換爲 props,能夠經過 this.props.xxx 獲取 state中的數據,這個數據是響應式的,只要 state 變化,這裏就更新,若是組件不須要從 state 中獲取數據,這裏參數能夠爲 null
// mapDispatchToProps 將 action 中的方法轉換爲 props, 能夠經過 this.props.xxx 調用
複製代碼
在 App.js 中 引入 Counter 組件redux
import React from 'react';
import './App.css';
import Counter from './components/Counter'
function App() {
return (
<div className="App">
<header className="App-header">
<Counter></Counter>
</header>
</div>
);
}
export default App;
複製代碼
建立actinos文件夾,用來存儲各個組件中須要定義的方法文件瀏覽器
在 actinos 文件夾下建立 actionsTypes.js 文件,用來存儲 action 和 reducer 相對應的指令app
export const ADD = 'ADD'
export const SUB = 'SUB'
複製代碼
在 actions 文件夾下建立 action.js 文件,用來存儲各類方法
import {ADD, SUB} from './actionsTypes'
export const sub = () => dispatch => { // 定義一個減1的函數,返回一個參數爲 dispatch 的函數
console.log('觸發了sub')
return dispatch({ // 將 action dispatch 到 reducer,這時會打印 ’觸發了reducer‘
type: SUB
})
}
export const add = () => dispatch => {
console.log('觸發了add')
return dispatch({
type: ADD
})
}
複製代碼
建立 reducers 文件夾, 用來存放各個reducer, 每一個reducer 至關於一個子 state
在 reducers 文件夾下建立 index.js 文件 用來合併因此的 reducer
import { combineReducers } from "redux"; // 引入 combinReducers 函數,用來合併多個 reducer
import reducer from './reducer'
export default combineReducers({
reducer
})
複製代碼
在 reducers 文件夾下建立 reducer.js 文件
import {ADD, SUB} from '../actions/actionsTypes'
const initState = { // 初始化一個 state
num: 0
}
export const reducer = (state = initState, action) => { // 每一個 reducer 函數接收 state 和 action 兩個參數,action 由 action.js 中的方法 dispatch 過來的
console.log('觸發了reducer')
switch(action.type) {
case ADD: // 經過判斷 action 類型,作出對應的操做,返回新的 state 給 store
return {
num: state.num+1
}
case SUB:
return {
num: state.num-1
}
default:
return state
}
}
export default reducer
複製代碼