6、谷粒后台使用redux管理数据
环境准备
安装插件
1
yarn add redux react-redux redux-thunk redux-devtools-extension
在入口
index.js
文件中包装1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19/**
* 入口文件
*/
import React from 'react';
// 引入redux
import { Provider } from 'react-redux'
import ReactDOM from 'react-dom';
import memoryUtils from './utils/memoryUtils'
import storageUtils from './utils/storageUtils'
import App from './App';
import store from './redux/store'
const user = storageUtils.getUser()
memoryUtils.user = user
ReactDOM.render(
// 包装
(<Provider store={store}><App /></Provider>),
document.getElementById('root')
);在
src
目录下创建redux
文件,分别创建如下文件action-type.js
1
2
3/**
* 包含n个action的type常量标识名称的模块
*/actions.js
1
2
3
4
5/**
* 包含n个action creator函数的模块
* 同步:对象{}
* 异步:thunk
*/reducer.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34/**
* 用来根据老的state和指定的action生成并返回新的state的函数
*/
import storageUtils from '../utils/storageUtils'
import { combineReducers } from 'redux'
const initHeadTitle = ''
// 用来管理头部标题的reducer
function headTitle (state = initHeadTitle, action) {
switch (action.type) {
default:
return state
}
}
// 用来管理用户的reducer
const initUser = storageUtils.getUser()
function User (state = initUser, action) {
switch (action.type) {
default:
return state
}
}
// 向外默认暴露的是合并产生的总的reducer函数
// 管理的总的结构:
/**
{
headTitle:'首页',
user:{}
}
*/
export default combineReducers({
headTitle,
User
})store.js
1
2
3
4
5
6
7
8
9/**
* redux核心管理对象
*/
// 向外默认暴露store
import { createStore, applyMiddleware } from 'redux'
import thunk from 'redux-thunk'
import { composeWithDevTools } from 'redux-devtools-extension'
import reducer from './reducer'
export default createStore(reducer, composeWithDevTools(applyMiddleware(thunk)))
头部标题
显示
此时已经在redux中存储了值,只需要包装ui组件,使其获取到redux中的值即可。
编辑
header.jsx
1
2
3
4
5
6
7
8
9
10
11// 1. 引入组件
import { connect } from 'react-redux'
// 2. 包装暴露对象
export default connect(
(state) => ({ headTitle: state.headTitle }),
{}
)(withRouter(Header))
// 3. 修改获取title的方法
const title = this.props.headTitle
修改
修改标题发生在点击左侧菜单栏之后。因此逻辑大概是当点击某个菜单后重新设置redux中的值。
编辑
action-type.js
文件,新增一个标识1
export const SET_HEAD_TITLE = 'set_head_title'
编辑
actions.js
文件,定义一个设置头部标题的action
1
2
3import { SET_HEAD_TITLE } from './action-type'
// 设置头部标题的同步action
export const setHeadTitle = (headTitle) => ({ type: SET_HEAD_TITLE, data: headTitle })更新
reducer.js
1
2
3
4
5
6
7
8
9
10import { SET_HEAD_TITLE } from './action-type'
// 用来管理头部标题的reducer
function headTitle (state = initHeadTitle, action) {
switch (action.type) {
case SET_HEAD_TITLE:
return action.data
default:
return state
}
}修改
left-nav.jsx
文件1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29// 1. 引入插件
import { connect } from 'react-redux'
// 2. 引入设置标题的actions(函数)
import { setHeadTitle } from '../../redux/actions'
// 为点击绑定事件
if (this.hasAuth(item)) {
if (!item.children) {
// 当前要显示的item
if (item.key === path || path.indexOf(item.key) === 0) {
// 设置点击事件
this.props.setHeadTitle(item.title)
}
// 向pre中添加
pre.push(
<Menu.Item key={item.key}>
<IconFont type={item.icon} />
<Link
to={item.key}
// 设置点击事件
onClick={() => this.props.setHeadTitle(item.title)}
>
{item.title}
</Link>
</Menu.Item>
)
}
}
// 4. 封装暴露对象
export default connect((state) => ({}), { setHeadTitle })(withRouter(LeftNav))
用户信息
定义
actions-type
1
2
3
4// 接收用户信息
export const RECEIVE_USER = 'receive_user'
// 显示错误信息
export const SHOW_ERROR_MSG = 'show_error_msg'定义
actions
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30import { SET_HEAD_TITLE, RECEIVE_USER, SHOW_ERROR_MSG } from './action-type'
import { reqLogin } from '../api'
import storageUtils from '../utils/storageUtils'
// 接收用户的同步action
export const recevieUser = (user) => ({ type: RECEIVE_USER, user })
// 显示错误信息的同步action
export const showErrorMsg = (errorMsg) => ({ type: SHOW_ERROR_MSG, errorMsg })
// 登录的异步action
export const login = (username, password) => {
return async dispath => {
// 1. 执行异步ajax请求
const result = await reqLogin(username, password)
if (result.status === 0) {
// 2.1 成功=>分发 成功的同步action
const user = result.data
// 保存到local中
storageUtils.saveUser(user)
// 分发接收用户的同步action
dispath(recevieUser(user))
} else {
// 2.2 失败=>分发 失败的同步action
const msg = result.msg
// message.error(msg)
dispath(showErrorMsg(msg))
}
}
}为
reducer
增加新的处理方式1
2
3
4
5
6
7
8
9
10
11
12
13
14import { SET_HEAD_TITLE, RECEIVE_USER, SHOW_ERROR_MSG } from './action-type'
function user (state = initUser, action) {
switch (action.type) {
case RECEIVE_USER:
console.log(action.user);
return action.user
case SHOW_ERROR_MSG:
const errorMsg = action.errorMsg
return { ...state, errorMsg }
default:
return state
}
}在
login.jsx
组件中使用1
2
3
4
5
6// 1. 引入
import { connect } from 'react-redux'
import { login } from '../../redux/actions'
// 2. 包装
export default connect((state) => ({ user: state.user }), { login })(Login)
// 3. 使用 (this.props.user)
退出
actions.js
1
2
3
4
5
6// 退出登录同步
export const logout = () => {
// 删除local中的user
storageUtils.removeUser()
return { type: RESET_USER }
}reducer.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14function user (state = initUser, action) {
switch (action.type) {
case RECEIVE_USER:
console.log(action.user);
return action.user
case SHOW_ERROR_MSG:
const errorMsg = action.errorMsg
return { ...state, errorMsg }
case RESET_USER:
return {}
default:
return state
}
}
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 小康博客!
评论
TwikooWaline