# 一、redux的基本使用
# 1、写action
//actions.js
export const incAction = (num) => ({ type: "INCREMENT", num });
export const decAction = (num) => ({ type: "DECREMENT", num });
export const addAction = (num) => ({ type: "ADD_NUMBER", num });
export const subAction = (num) => ({ type: "SUB_NUMBER", num });
export const exAction = { caonima: "caonidaye", type: "SUB_NUMBER" };
// 1、填写ation的类容,不一定要是函数,可以是对象等
# 2、state和reducer
//reducer.js
// 2、写出state的初始内容和reducer
const initState = {
money: 200,
caonima: "caolima",
};
//3、reducer是参数为state和action的纯函数,返回的也是新state
const reducer2 = (state = initState, action) => {
console.log(action, state, { ...state, caonima: "caonidaye" });
switch (action.caonima) {
case "caonidaye":
return { ...state, caonima: "caonidaye" };
default:
return state;
}
};
const reducer = (state = initState, action) => {
switch (action.type) {
case "INCREMENT":
return { ...state, money: state.money + 1 };
case "DECREMENT":
return { ...state, money: state.money - 1 };
case "ADD_NUMBER":
return { ...state, money: state.money + action.num };
case "SUB_NUMBER":
return { ...state, money: state.money - action.num };
default:
return state;
}
};
export { reducer, reducer2 };
# 3、集合reducer,创建store
//store/index.js
import { createStore, combineReducers } from "redux";
import { reducer, reducer2 } from "./reducer";
//多个reducers时可以使用combineReducers
const reducers = combineReducers({
reducer,
reducer2,
});
//3、先将不同的集合合并,使用的是combineReducers
//4、再创建createStore
const store = createStore(reducers);
export default store;
# 4、使用store
import React, { Component } from "react";
// 5、引入store
import store from "../store/index.js";
// 6、在组件中引入ation
import { exAction, subAction } from "../store/actions";
export class home extends Component {
state = {
money: 200,
caonima: "cao",
};
kuiqian = (num) => {
// 7、在事件中使用 store.dispatch触发action
store.dispatch(subAction(num));
// console.log("xuekui");
};
jiaqian = () => {
store.dispatch(exAction);
};
componentDidMount() {
store.subscribe(() => {
// 8、在指定的函数位置获取state,然后使用setState修改
this.setState({ money: store.getState().reducer.money });
console.log(store.getState().reducer2.caonima);
this.setState({ caonima: store.getState().reducer2.caonima });
});
}
render() {
return (
<div>
我是home{this.state.money}
<hr />
{this.state.caonima}
<button onClick={() => this.jiaqian()}>加钱</button>
<button onClick={() => this.kuiqian(200)}>亏钱</button>
</div>
);
}
}
export default home;
# 二、redux-actions
reducer使用switch case语句进行action类型判断,当action很多时候,reducer内容就不那么直观了。redux-actions简化了reducer和action的联系
# 1、写action的方式改变
引入了createAction:const 返回action对象的函数 = createAction(action 的 type 值);
//actions/common.js
import { createAction } from 'redux-actions'
// 1、下载与引入
import * as common from '@apis/common'
import { createAjaxAction } from '@configs/common'
// 2、注册action
export const requestLogin = createAction('request login')
export const recevieLogin = createAction('receive login')
export const login = createAjaxAction(common.login, requestLogin, recevieLogin)
export const setGformCache2 = createAction('set gform cache2')
export const clearGformCache2 = createAction('clear gform cache2')
//actions/tabList.js
import { createAction } from 'redux-actions'
export const requestTabList = createAction('request tab list')
export const updateTabList = createAction('update tab list')
export const updateTabChecked = createAction('update tab checked')
export const deleteTabFromList = createAction('delete tab from list');
# 2、reducer
import { handleActions } from 'redux-actions',引入了handleActions({ [type值]: (state, action) => { return 要修改的新值 } }, 数据初始值)
// reducers/common.js
import { handleActions } from 'redux-actions'
// 登陆返回结果
const loginState = () => ({ })
export const loginResponse = handleActions({
'request login'(state, action) {
return { ...state, loading: true }
},
'receive login'(state, action) {
// eslint-disable-next-line no-unused-vars
const { req, res } = action.payload
return { data: res, loading: false }
},
}, loginState())
// gForm2.0缓存
const cache2 = () => ({})
export const gFormCache2 = handleActions({
'set gform cache2'(state, action) {
const { cacheKey, cacheContent } = action.payload
if (cacheKey === undefined) {
throw new Error('cacheKey不能是undefined')
}
if (cacheContent === undefined) {
throw new Error('cacheContent不能是undefined')
}
state[cacheKey] = { ...state[cacheKey], ...cacheContent }
return { ...state }
},
'clear gform cache2'(state, action) {
return cache2()
},
}, cache2())
// gForm2.0头部搜索类别
const allRetrievalState = {
list: [],
}
export const allRetrievalResult = handleActions({
'request all retrieval'(state, action) {
return { ...state, loading: true }
},
'receive all retrieval'(state, action) {
// eslint-disable-next-line no-unused-vars
const { req, res } = action.payload
return { ...res.data, loading: false }
},
}, allRetrievalState)
// reducers/tabList.js
import { handleActions } from 'redux-actions'
const tabList = JSON.parse(sessionStorage.getItem('tabList'))
const initialState = {
list: tabList ? tabList.list : [],
activeKey: tabList ? tabList.activeKey : '',
}
const tabListResult = handleActions({
'request tab list'(state, action) {
return { ...state, loading: false }
},
'update tab list'(state, action) {
const data = action.payload
const findList = state.list.find(tab => tab.key === data.key)
const list = findList === undefined ? [...state.list, data] : state.list
sessionStorage.setItem('tabList', JSON.stringify({ list, activeKey: data.key, loading: false }))
return { list, activeKey: data.key, loading: false }
},
'update tab checked'(state, action) {
const { activeKey } = action.payload;
sessionStorage.setItem('tabList', JSON.stringify({ ...state, activeKey, loading: false }))
return { ...state, activeKey, loading: false }
},
'delete tab from list'(state, action) {
const { targetKey } = action.payload
const list = []
let delIndex = 0
let { activeKey } = state
state.list.map((tab, index) => {
tab.key === targetKey ? delIndex = index : list.push(tab)
})
if (state.activeKey === targetKey) {
// eslint-disable-next-line no-nested-ternary
activeKey = list[delIndex] ? list[delIndex].key :
(list[delIndex - 1] ? list[delIndex - 1].key : '')
}
sessionStorage.setItem('tabList', JSON.stringify({ list, activeKey, loading: false }))
return { list, activeKey, loading: false }
},
}, initialState)
export { tabListResult as default }
// reducers/index.js
import { combineReducers } from 'redux'
import * as tabList from './tabList'
import * as common from './common'
const rootReducer = combineReducers({
config: (state = {}) => state,
...tabList,
...common,
})
export default rootReducer
# 3、store,中间件与使用
// app\middleware\configureStore.js
import { createStore, applyMiddleware } from 'redux'
import thunkMiddleware from 'redux-thunk'
import rootReducer from '@reducers'
import { logger, router, reduxRouterMiddleware } from './index'
const nextReducer = require('@reducers')
export default function configure(initialState) {
// console.log('initialState', initialState)
const create = window.devToolsExtension
? window.devToolsExtension()(createStore)
: createStore
const createStoreWithMiddleware = applyMiddleware(
reduxRouterMiddleware,
thunkMiddleware,
logger,
// router,
)(create)
const store = createStoreWithMiddleware(rootReducer, initialState)
if (module.hot) {
module.hot.accept('../reducers', () => {
store.replaceReducer(nextReducer)
})
}
return store
}
store的全局配置
import 'babel-polyfill'
import React from 'react'
import ReactDOM from 'react-dom'
import { Provider } from 'react-redux'//企业级的使用方法
import '@config'
import Routes from '@configs/router.config'
import configure from '@middleware/configureStore'//引入创建的store
const store = configure({ })
ReactDOM.render(
<Provider store={store}>
<Routes />
</Provider>,
document.getElementById('root'),
)
组件里的使用
import React, { Component } from 'react'
import { connect } from 'react-redux'
import { Link } from 'react-router'
import { Button, Spin, Form, Input, Table } from 'antd'
import {
fetchHouseCheckList,
} from 'actions/house'
if (process.env.NODE_ENV === 'development') {
console.log('development')
}
const FormItem = Form.Item
@Form.create({})
@connect((state, props) => ({
config: state.config,
houseCheckSearchResult: state.houseCheckSearchResult,
}))//将数据以props的形式注入子组件,返回的时一个对象
export default class app extends Component {
constructor(props) {
super(props)
this.state = {
data: {
},
}
this._handleSubmit = this._handleSubmit.bind(this)
}
componentDidMount() {
this.props.dispatch(fetchHouseCheckList({ currentPage: 1 }, (respose) => {}))
}
_handleSubmit(currentPage) {
this.props.dispatch(fetchHouseCheckList({ keyword: '' }))
}
columns() {
return [
{
title: '序号',
key: 'index',
width: '5%',
render: (text, recordId, index) => <span>{index + 1}</span>,
},
{
title: '建筑物地址',
dataIndex: 'address',
key: 'address',
width: '25%',
},
{
title: '行政区划',
dataIndex: 'division',
key: 'division',
width: '10%',
},
{
title: '管辖单位',
dataIndex: 'institutions',
key: 'institutions',
width: '10%',
},
{
title: '管辖警员',
dataIndex: 'policeName',
key: 'policeName',
width: '10%',
},
{
title: '房屋状态',
dataIndex: 'houseStatus',
key: 'houseStatus',
width: '15%',
},
{
title: '地址属性',
dataIndex: 'addressType',
key: 'addressType',
width: '15%',
},
{
title: '操作',
key: 'operate',
// fixed: 'right',
width: '10%',
render: function (text, record, index) {
return (
<span>
<Button type="primary" size="small">
<Link to={`/houseDetail/${text.id}`}>查看</Link>
</Button>
</span>
)
},
},
]
}
tableData() {
return this.props.houseCheckSearchQuery.list
}
render() {
const { houseCheckSearchResult, form } = this.props
const { getFieldDecorator } = form
// console.log(houseCheckSearchResult)
return (
<div className="page">
<div className="search" style={{ marginBottom: '10px' }}>
<Form onSubmit={this._handleSubmit} layout="inline">
<FormItem label="关键字">
{
getFieldDecorator('keyword', {
rules: [{
required: false,
}],
})(<Input placeholder="请输入关键字" size="default" style={{ width: '200px' }} />)
}
</FormItem>
<Button type="primary" onClick={this._handleSubmit}>确定</Button>
</Form>
</div>
<Spin spinning={houseCheckSearchResult.loading}>
<Table
rowKey="id"
dataSource={houseCheckSearchResult.list}
columns={this.columns()}
pagination={{ total: houseCheckSearchResult.totalCount, pageSize: houseCheckSearchResult.pageSize }}
scroll={{ y: true }}
rowClassName={(record, index) => (record.id === 1 ? 'red' : 'base')}
/>
</Spin>
</div>
)
}
}
# 4、connect
将数据以props的形式注入子组件,返回一个对象
import React, { PureComponent } from 'react'
import { connect } from 'react-redux'
import { decAction, addAction, getHomeAction } from '../store/action'
class Home extends PureComponent {
componentDidMount() {
this.props.getData()
}
render() {
console.log(this.props)
return (
<div>
<h1>home page</h1>
<h2>余额:{this.props.money}</h2>
<button onClick={e => this.props.subNumber(1)}>付钱</button>
<button onClick={e => this.props.makeMoney(50)}>收钱</button>
<h2>用户信息</h2>
<ul>
{
this.props.userinfo.map(item => {
return (
<li key={item.key}>{item.name}--{item.age}--{item.job}</li>
)
})
}
</ul>
</div>
)
}
}
//和名字一样,比较好理解
const mapStateToProps = (state, props) => {
console.log(state, props)
return {
money: state.money,
userinfo: state.userInfo,
info: props.info
}
}
const mapDispatchProps = (dispatch) => {
return {
subNumber: (num) => {
dispatch(decAction(num))
},
makeMoney: (num) => {
dispatch(addAction(num))
},
getData: () => {
dispatch(getHomeAction)
}
}
}
export default connect(mapStateToProps, mapDispatchProps)(Home)