经过阅读阮一峰老师的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
复制代码