redux的创建
redux的使用需要创建四个文件,分别为action,reducer,store和constant
- action:专门用于为组件生成action对象的文件,每一个需要用到redux的组件都需要创建一个对应的action文件
(创建action对象,即创建组件想要加工数据的方式)
/*
该文件专门用于为Count组件生成action对象
*/
import { INCREMENT, DECREMENT } from '../constant';
// 同步action,就是指action的值为Object类型的一般对象
export const createIncrementAction = data => { return { type: INCREMENT, data } }
export const createDecrementAction = data => { return { type: DECREMENT, data } }
// 异步action,就是指action的值为函数,异步action中一般都会调用同步action,异步action不是必须要用的
export const createIncrementAsyncAction = (data, time) => {
return (dispatch) => {
setTimeout(() => {
dispatch(createIncrementAction(data))
},time)
}
}
- reducer:用于手动创建一个为组件服务的reducer,其本质是一个函数
(根据组件传入action参数类型判断如何加工数据)
/*
1.该文件用于手动创建一个为Count组件服务的reducer,其本质是一个函数
2.reducer函数会接到两个参数,分别为之前的状态(preState),动作对象(action)
*/
import {INCREMENT,DECREMENT} from '../constant';
// 初始化preState的值,如果为undefined则为0
const initState = 0
export default function countReducer(preState = initState, action) {
// 从action对象中获取: type、data
const { type, data } = action
// 根据type决定如何加工数据
switch (type) {
case INCREMENT:
return preState + data
case DECREMENT:
return preState - data
default:
return preState
}
}
- store:专门用于暴露一个store对象,整个引用只有一个store对象
(redux核心文件)
/*
该文件专门用于暴露一个store对象,整个引用只有一个store对象
*/
// 引入createStore,专门用于创建redux中最为核心的store对象
// applyMiddleware用于引用thunk中间件
// combineReducers用于汇总所有的reducers变为一个reducer
import { createStore, applyMiddleware, combineReducers } from 'redux'
// 引入为Count组件服务的reducer
import countReducer from './reducers/count';
// 引入为Person组件服务的reducer
import personReducer from './reducers/person';
// 引入redux-thunk,用于支持异步action
import thunk from 'redux-thunk';
const reducer = combineReducers({
countReducer,
personReducer
})
const store = createStore(reducer, applyMiddleware(thunk))
export default store
- constant:用于定义action对象中的type类型的常量值,便于管理的同时防止写错
(便于后期维护)
/*
该模块用于定义action对象中的type类型的常量值,便于管理的同时防止写错
*/
// 定义加法
export const INCREMENT = 'increment'
// 定义减法
export const DECREMENT = 'decrement'
// 定义添加一个人的信息
export const Add_Person = 'add_person'
App组件的使用
组件的挂载应该引入容器组件,而不是UI组件
import React, { Component } from 'react';
import Count from './containers/Count';
import Person from './containers/Person';
export default class App extends Component {
render() {
return (
<div>
<Count />
<hr />
<Person/>
</div>
);
}
}
入口文件index.js的使用
入口文件中需要注意的是
- store的状态更新不会自动重新渲染页面,需要subscribe()监测store状态更新,而react-redux中的connect可以自动监测store状态更新,所以可以略去
- 在容器组件与redux、UI组件相关联时,redux通过props传递store状态给容器组件,由于每个容器组件都要传过于繁琐,使用Provider可以给App里的所有容器组件匹配store
import React from 'react';
import ReactDom from 'react-dom';
import store from './redux/store';
import { Provider } from 'react-redux'
import App from './App';
ReactDom.render(
// react-redux的Provide可以给App里的所有组件匹配store
<Provider store={store}>
<App />
</Provider>,
document.getElementById('root')
)
// 监测store状态更新
// react-redux的connect可以自动检测store状态更新
// store.subscribe(() => {
// ReactDom.render(<App />, document.getElementById('root'))
// })
容器组件
- 由于UI组件不能直接从redux中的store中获取状态state以及获取更新状态的方法,所以容器组件就充当了一个中间桥梁的作用
- 引入connect,connect()()中的第二个括号连接UI组件,第一个括号用以映射store中的状态和操作状态的方法
import React, { Component } from 'react';
import { connect } from 'react-redux';
import {
createIncrementAction,
createDecrementAction,
createIncrementAsyncAction
} from '../../redux/actions/count';
class Count extends Component {
increment = () => {
this.props.increment(this.selectNumber.value*1)
}
decrement = () => {
this.props.decrement(this.selectNumber.value*1)
}
incrementIfOdd = () => {
if (this.props.count % 2 !== 0) {
this.props.increment(this.selectNumber.value*1)
}
}
incrementAsync = () => {
this.props.incrementAsync(this.selectNumber.value*1, 500)
}
render() {
return (
<div>
<h2>当前求和为:{ this.props.count }</h2>
<select ref={c => this.selectNumber = c}>
<option value='1'>1</option>
<option value='2'>2</option>
<option value='3'>3</option>
</select>
<button onClick={this.increment}>+</button>
<button onClick={this.decrement}>-</button>
<button onClick={this.incrementIfOdd}>当前求和为奇数再加</button>
<button onClick={this.incrementAsync}>异步加</button>
</div>
);
}
}
export default connect(
state => ({ count: state.countReducer }), // 映射状态
{
increment: createIncrementAction,
decrement: createDecrementAction,
incrementAsync: createIncrementAsyncAction
} // 映射操作状态的方法
)(Count)
在引入react-redux之前使用store
- 需要引入store文件
- 使用dispatch(action)修改状态
- 使用getState()获取store状态
import React, { Component } from 'react'
import store from '../../redux/store';
import { createIncrementAction, createDecrementAction, createIncrementAsyncAction} from '../../redux/count_action';
export default class Count extends Component {
//加法
increment = () => {
const {value} = this.selectNumber
// 通知redux加value
store.dispatch(createIncrementAction(value * 1))
}
//减法
decrement = () => {
const {value} = this.selectNumber
// 通知redux减value
store.dispatch(createDecrementAction(value * 1))
}
//奇数再加
incrementIfOdd = () => {
const { value } = this.selectNumber
let count = store.getState()
// 通知redux加value
if(count % 2 !== 0){
store.dispatch(createIncrementAction(value * 1))
}
}
//异步加
incrementAsync = () => {
const { value } = this.selectNumber
store.dispatch(createIncrementAsyncAction(value * 1, 500))
}
render() {
return (
<div>
<h1>当前求和为:{ store.getState() }</h1>
<select ref={c => this.selectNumber = c}>
<option value="1">1</option>
<option value="2">2</option>
<option value="3">3</option>
</select>
<button onClick={this.increment}>+</button>
<button onClick={this.decrement}>-</button>
<button onClick={this.incrementIfOdd}>当前求和为奇数再加</button>
<button onClick={this.incrementAsync}>异步加</button>
</div>
)
}
}